假设我有类Player
并且我想要一个布尔方法来检查玩家是否受到攻击:
class Player
attr_accessor :name, :health, :attacked?
def initialize(name)
@name = name
@health = 100
@attacked? = false
end
end
我收到语法错误:
SyntaxError: (irb):14: syntax error, unexpected '='
@attacked? = false
^
from /usr/bin/irb:12:in `<main>'
从attacked
中删除问号可以解决问题,但我认为在我的代码中使用attacked?
更符合惯例。放弃问号并不是什么大不了的事,但为什么zero?
和nil?
约会时@variables?
和def methods?=
约定无效?
答案 0 :(得分:12)
请注意,如果您注释掉导致错误的行(@attacked? = false
),您仍会收到与问号相关的错误:
NameError: invalid attribute name `attacked?'
问题是?
不是变量名中的有效字符。第一个错误(您看到的SyntaxError
)是在解析时引起的并立即捕获。当Ruby尝试评估代码并且无法创建名称包含无效字符的实例变量时,会导致第二个错误。
问号 是方法名称末尾的有效字符(实际上可以在其中的任何位置使用?
的方法名称,但你不能直接调用这样的方法。)
实现目标的一种方法是:
class Player
attr_accessor :name, :health, :attacked
alias :attacked? :attacked
def initialize(name)
@name = name
@health = 100
@attacked = false
end
end
这会使attacked
没有问号,但会将attacked?
添加为别名。
答案 1 :(得分:3)
之前我遇到过同样的问题,并希望我可以使用尾随问号制作实例变量。这似乎是Ruby语法中的一个极端情况。看看这个:
>> 1 ? 2 : 3
=> 2
>> 1?2:3
=> 2
>> @a = true
=> true
>> @a?1:2
=> 1
>> a = true
=> true
>> a ? 1 : 2
=> 1
>> a?1:2
SyntaxError: (irb):9: syntax error, unexpected ':', expecting $end
因此,?
符号在Ruby的语法中被重载 - 它用于三元运算符和,作为方法名称的有效标识符的一部分。这导致了最后一种情况的模糊性,其中Ruby的词法分析器似乎将a?
作为单个标记咬掉,这使得它无法正确解析其余的三元运算符。使用实例变量,这不可能发生。
同样,我同意允许实例变量名称中的问号非常有用,当然比使三元运算符的一些模糊用法更加有价值。