2009-08-11 209 views
30

學習ruby。我的印象就是那個如下布爾屬性應該被命名爲:Ruby:布爾屬性命名約定和使用

my_boolean_attribute? 

但是,試圖做到以下幾點,當我得到語法錯誤:「?」

class MyClass 
    attr_accessor :my_boolean_attribute? 

    def initialize 
    :my_boolean_attribute? = false 
    end 
end 

顯然紅寶石仇富。這是慣例嗎?我究竟做錯了什麼?

回答

40

編輯:三年後;時代,他們是 - 起了變化...

Julik's answer爲解決這個問題,這些天最簡單,最好的方法:

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進行 - 畢竟,這可能是明文規定你直接使用布爾屬性。通常,當我實現一個方法,其布爾型返回值基於稍微複雜的條件而不僅僅是屬性的值時,我保存問號後綴。

乾杯!


編輯,兩年後,最近的評論後:

  1. 紅寶石強制執行特定的命名約定。 Ruby中的符號不​​能有問號。因此,:my_boolean_attribute?的調用都將失敗,並顯示NameError編輯:不正確,只需使用引號語法表示符號,例如:"my_attribute?"
  2. 符號是不可變的,試圖分配給一個將會拋出一個SyntaxError
+6

Rubyist通常不會在變量名稱或方法名稱中使用is_前綴。真棒嗎?而不是is_awesome? – 2009-08-11 22:23:48

+0

好點,weppos。編輯'is_'以避免混淆後人;-) – 2009-08-11 22:25:41

+0

從這個答案我收集有沒有一個真正的約定? :/ – 2011-04-27 22:17:29

5

?是方法名稱的約定,而不是變量。您不能使用名爲@foo?的實例變量,但是您可以使用名爲@foo的變量,並根據需要命名(手動創建的)獲取方法foo?

+0

嗯,所以attr_accessor中幫手不會去掉'?'爲我而告終。很高興聽到它實際上不是公約的例子。以爲我瘋了。 – 2009-08-11 22:08:37

6

attr_accessor符號意味着變量名稱是@my_boolean_attribute,所以這就是你應該設置的(不是符號)。

另外,你不能使用?對於變量,只是方法名稱。

+0

ty爲符號捕獲。 self.my_boolean_attribute會正常工作嗎? – 2009-08-11 22:10:16

+0

是的,它應該。 – 2009-08-12 14:14:09

+0

哦,讓我加 - 只在實例方法中。在類作用域中,它將查找一個類作用域變量(@@ my_boolean_attribute)。當然,我不需要告訴你,但我想確保我所說的技術上是正確的。 – 2009-08-12 18:49:14

3

猴補丁元編程 - 也許它可以變得更優雅,這僅僅是一個快速的草案,我沒有做過元編程了一小會兒......

# 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? 

用這種方法,你可以幹,並獲得好的問號。您可能需要選擇比「bool_attr」更好的名稱,例如「bool_attr_accessor」或類似的名稱。

我所做的定義有點胡思亂想,因爲問號出現在原始符號中。可能更清晰的方法是避免符號名稱中的問號,並在方法的定義過程中追加它 - 應該不那麼令人困惑。

哦,差點忘了,包括強制性的鏈接:Seeing metaclasses clearly

+0

+1鏈接!這種情況下可能不會添加便利方法,因爲它不符合約定。我不想混淆別人。雖然這些想法會被其他問題愉快地蠶食掉! – 2009-08-11 22:38:20

+1

如果你在一個團隊中維護它,我想這種問題應該在評論中進行深入討論 - 在某些情況下它可能是有意義的,在某些情況下它不會。我沒有在一個團隊中編寫Ruby代碼,所以我傾向於採取一種讓我至少注意LOC的方法。 – 2009-08-11 23:00:14

+0

+1。如果只爲元智慧... – 2009-08-12 15:59:04

38

快速添加一個「問題的方法」的最簡單方法是使用別名爲你的讀者的方法

class Foo 
    attr_accessor :dead 
    alias_method :dead?, :dead # will pick up the reader method 
end 
+0

真棒!我一直在做這件事。 – 2009-08-13 15:25:11

+0

通過使用這個,你可以同時使用'dead'和'dead?',對嗎?但只允許通過「死」設置? – 2011-04-27 22:19:32

+3

設置保持通過「死=」 – Julik 2012-06-30 22:51:11