Ruby:布尔属性命名约定和使用

时间:2009-08-11 21:52:20

标签: ruby attributes conventions boolean-expression

学习红宝石。我的印象是布尔属性的名称应如下:

my_boolean_attribute?

但是,尝试执行以下操作时出现语法错误:

class MyClass
  attr_accessor :my_boolean_attribute?

  def initialize
    :my_boolean_attribute? = false
  end
end

显然红宝石讨厌“?”。这是惯例吗?我做错了什么?

6 个答案:

答案 0 :(得分:42)

编辑:三年后;时代,他们是a-changin'......

Julik's answer是解决这个问题的最简单,最好的方法:

class Foo
  attr_accessor :dead
  alias_method :dead?, :dead # will pick up the reader method
end

对于后代,我对原始问题的回答如下......


简短版本:

您不能在实例变量的名称中使用问号。

版本较长:

例如,attr_accessor :foo - 它的简单地概念性地为以下内容提供了一些语法糖:

def foo
  @foo
end

def foo=(newfoo)
  @foo = newfoo
end

此外,问号后缀大多只是一个约定,表示方法的返回值是布尔值。

我能在这里得到的最佳近似值......

class MyClass

  def initialize
    @awesome = true
  end

  def awesome?
    @awesome
  end

end

在这种情况下,可能存在使用attr_accessor的情况 - 毕竟,您可能明确表示您正在使用布尔属性。通常,我在实现一个方法时保存问号后缀,该方法的布尔返回值基于稍微复杂的条件,而不仅仅是属性的值。

干杯!


编辑,两年后,在最近的评论之后:

  1. Ruby强制执行某些命名约定。 Ruby中的符号不​​能有问号。因此,:my_boolean_attribute?的调用都将失败并显示NameError编辑:不正确,只需使用引号的符号语法,例如:"my_attribute?"
  2. 符号是不可变的,尝试分配符号将抛出SyntaxError

答案 1 :(得分:39)

快速添加“问题方法”的最简单方法是为读者方法使用别名

class Foo
  attr_accessor :dead
  alias_method :dead?, :dead # will pick up the reader method
end 

答案 2 :(得分:6)

attr_accessor符号表示变量名称为@my_boolean_attribute,因此您应该设置(而不是符号)。

另外,你不能使用?对于变量,只是方法名称。

答案 3 :(得分:5)

?是方法名称的约定,而不是变量。您不能使用名为@foo?的实例变量,但是如果您愿意,可以使用名为@foo的变量并命名(手动创建的)getter方法foo?

答案 4 :(得分:3)

猴子修补元编程 - 也许它可以变得更优雅,这只是一个快速的草稿,我还没有做过一段时间的元编程......

 # inject the convenience method into the definition of the Object class
 class Object
   def Object::bool_attr(attrname)
     class_eval { define_method(attrname.to_s,
          lambda { instance_variable_get('@' + attrname.to_s.chop) }) }
     class_eval { define_method(attrname.to_s.chop+"=",
          lambda { |x| instance_variable_set('@'+attrname.to_s.chop, x) }) }
   end
 end

 ### somewhere later

 class MyClass

   bool_attr :my_boolean_attribute?

   def initialize
     @my_boolean_attribute = true
   end
 end

 # yet even more later

 foo = MyClass.new
 bar = MyClass.new

 foo.my_boolean_attribute = 1
 puts foo.my_boolean_attribute?
 puts bar.my_boolean_attribute?

通过这种方法,你可以干,并获得好的问号。您可能需要选择比“ bool_attr ”更好的名称,例如“ bool_attr_accessor ”或类似名称。

我所做的定义有点胡思乱想,从某种意义上说,问号出现在原始符号中。可能更清洁的方法是避免符号名称中的问号,并在方法的定义中附加它 - 应该不那么混乱。

哦,差点忘了加入强制性链接:Seeing metaclasses clearly

答案 5 :(得分:0)

我仔细查看了答案,尽管可接受的答案是正确的,但它在课堂上引入了“额外”的噪音。我建议解决此问题的方法是:

class Animal
  attr_writer :can_swim
  def initialize(animal_type_name)
    @can_swim = true
    @animal_type_name = animal_type_name
  end


  def can_swim?
    @can_swim
  end

  def to_s
    @animal_type_name
  end
end

dog = Animal.new('Dog in a bag')
dog.can_swim = false
puts "Can this #{dog} Swim? --- [#{dog_without_legs.can_swim? ? 'YEP!' : 'NOPE!'}]"