5

假设我有课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?=无效?

4

2 回答 2

13

请注意,如果您注释掉导致错误 ( @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?作为别名添加。

于 2012-12-22T20:37:26.690 回答
4

我以前遇到过同样的问题,希望我可以用一个尾随问号创建实例变量。这似乎是 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 语法中被重载——它用于三元运算符,作为方法名称的有效标识符的一部分。a?这在最后一种情况下会导致歧义,其中 Ruby 的词法分析器似乎将 t作为单个标记咬掉了,这使其无法正确解析三元运算符的其余部分。使用实例变量,这不会发生。

同样,我同意在实例变量名称中允许使用问号将非常有用,当然比使三元运算符的一些晦涩使用明确更有价值。

于 2012-12-22T20:06:50.057 回答