2012-12-22 41 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?作爲一個令牌,這讓它無法正確地解析了三元運算符的其餘部分不確定性。通過實例變量,這不會發生。

同樣,我同意,在實例變量名允許問號將是非常有用的,肯定比使得三元運營商非模糊的一些不起眼的用途更有價值。

相關問題