2012-12-22 38 views
5

说我有Player类,我想一个布尔值的方法来检查,如果玩家被攻击:在Ruby方法使用一个问号

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

'@ attacked'是一个实例变量,而不是一个方法。 '@attacked = false'; ......“def攻击? @attacked;结束' –

+3

我的猜测是你不能将问号作为变量名的一部分。这只适用于方法。另外,我不记得带有setter的单个问号方法。他们都是获得者。 –

+0

这是一个很好的观点。他们都是获得者。用问号创建一个setter会创建“attacked?=”方法,这也是无效的语法。所以我的代码也会有一个无效的变量名和一个无效的方法名。 – rubyuser1357796

回答

11

请注意,如果您注释掉线引起您的错误(@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?

+0

谢谢!我甚至没有考虑过使用别名。 – rubyuser1357796

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?作为一个令牌,这让它无法正确地解析了三元运算符的其余部分不确定性。通过实例变量,这不会发生。

同样,我同意,在实例变量名允许问号将是非常有用的,肯定比使得三元运营商非模糊的一些不起眼的用途更有价值。

相关问题