我正在学习 Ruby。我的印象是布尔属性应该按照以下方式命名:
my_boolean_attribute?
然而,当我尝试进行以下操作时,我会收到语法错误:
class MyClass
attr_accessor :my_boolean_attribute?
def initialize
:my_boolean_attribute? = false
end
end
显然,Ruby不喜欢“?”。这是惯例吗?我做错了什么吗?
我正在学习 Ruby。我的印象是布尔属性应该按照以下方式命名:
my_boolean_attribute?
然而,当我尝试进行以下操作时,我会收到语法错误:
class MyClass
attr_accessor :my_boolean_attribute?
def initialize
:my_boolean_attribute? = false
end
end
显然,Ruby不喜欢“?”。这是惯例吗?我做错了什么吗?
编辑:三年后,时代已经发生了变化...
Julik的回答是当今解决这个问题最简单、最好的方法:
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
——毕竟,明确表明你直接使用布尔属性。通常,我会将问号后缀保存下来,当我实现一个基于略微复杂的条件而非仅仅属性值的布尔返回值时,再使用它。:my_boolean_attribute?
将导致 NameError
错误。:"my_attribute?"
SyntaxError
。快速添加“问题方法”的最简单方法是使用你的读取器方法进行别名设置
class Foo
attr_accessor :dead
alias_method :dead?, :dead # will pick up the reader method
end
dead
和 dead?
,对吧?但是只允许通过 dead
进行设置? - Steven Jeuris attr_accessor
符号意味着变量名是 @my_boolean_attribute
,所以这就是您应该设置的内容(而不是符号)。
另外,您不能在变量中使用?,只能在方法名称中使用。
? 是方法名的惯例,而不是变量名。你不能使用名为@foo?
的实例变量,但是如果你想的话,可以使用名为@foo
的变量,并将(手动创建的)getter方法命名为foo?
。
猴子补丁元编程 - 或许可以让其更加优雅,这只是一个快速草稿,而且我已经有一段时间没有进行元编程了...
# 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?
我浏览了答案,尽管被接受的回答很到位,但它在类中引入了“额外”的噪音。我建议解决这个问题的方式是:
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!'}]"
:"my_boolean_attribute?"
,甚至是:"my boolean attribute?"
(不过如果没有使用send
的话,后者可能会有些困难哦!) - Andrew Grimm