2010-02-22 32 views
38

我試圖讓馬茨和弗拉納根的「Ruby編程語言」元編程章到我的頭上,但是我不明白,從下面的代碼片段輸出,我想出了:如何通過反射獲取由Ruby的Module類定義的常量?

p Module.constants.length   # => 88 
$snapshot1 = Module.constants  
class A 
    NAME=:abc 

    $snapshot2 = Module.constants 
    p $snapshot2.length    # => 90 
    p $snapshot2 - $snapshot1   # => ["A", "NAME"] 

end 
p Module.constants.length   # => 89 
p Module.constants - $snapshot1  # => ["A"] 
p A.constants      # => ["NAME"] 

書中指出,類方法constants將返回該類的常量列表(如在A.constants的輸出中所見)。 我試圖獲得爲Module類定義的常量列表,當我遇到上述奇怪的行爲。

A的常量顯示在Module.constants中。如何獲取Module類定義的常量列表?

docs狀態

Module.constants返回系統中定義的所有常量。包括所有類的名稱和方法

由於A繼承Module.constants它的實現,它是如何表現不同的基類和派生類型?

p A.class    # => Class 
p A.class.ancestors  # => [Class, Module, Object, Kernel] 

注:如果您使用Ruby 1.9的,constants將返回符號,而不是字符串數組。

+0

我回答了你的問題嗎?我問,因爲我的答案不是'接受',但沒有要求任何額外的信息... – 2010-02-26 20:53:50

+0

@Marc - 你的答案讓我回到更多的問題和更多的塗鴉和擦除。本週花費在試圖圍繞方法解決方案包圍我的頭......我仍然不清楚可能性是什麼 - 但是我認爲我對於它的工作原理有90%的把握。看到我的帖子下面。 – Gishu 2010-03-02 12:54:49

回答

47

好問題!

你的困惑是由於該類方法Module.constants隱藏實例方法Module#constantsModule

在Ruby 1.9,這已得到解決通過添加一個可選參數:

# No argument: same class method as in 1.8: 
Module.constants   # ==> All constants 
# One argument: uses the instance method: 
Module.constants(true) # ==> Constants of Module (and included modules) 
Module.constants(false) # ==> Constants of Module (only). 

在你上面的例子,A.constants呼叫Module#constants(實例方法),而Module.constants呼叫,那麼,Module.constants

在Ruby 1.9中,您因此想要調用Module.constants(true)

在Ruby 1.8中,可以調用Module上的實例方法#constants。你需要得到的實例方法,並將其綁定爲一個類的方法(使用不同的名稱):

class << Module 
    define_method :constants_of_module, Module.instance_method(:constants) 
end 

# Now use this new class method: 
class Module 
    COOL = 42 
end 
Module.constants.include?("COOL") # ==> false, as you mention 
Module.constants_of_module   # ==> ["COOL"], the result you want 

我希望我能夠完全反向移植了1.9的功能,1.8我backports寶石,但我可以」我想在Ruby 1.8中只能獲得一個Module的常量(不包括繼承的)。

編輯:只是改變了官方文件,以正確反映此...

+0

@Marc - 如果你能理解我的方法解析並確認它,將不勝感激。博客文章鏈接在我的帖子下面。謝謝並接受:) – Gishu 2010-03-02 13:08:15

3

我不得不重新回到了我的思維山洞馬克的響應之後一段時間。用更多代碼片段進行修剪,然後添加更多代碼片段。最後,當Ruby的方法解析看起來有意義時,將其寫成博客文章,以便我不會忘記。

記號:如果A」的eigenclass甲

A.constants被調用,方法解析(參照圖像中my blog post有一個視覺幫助)查找以下位置,以便

  • MyClass"Object"BasicObject"(singleton方法)
  • Class(例如方法)
  • Module(實例方法)
  • Object(實例方法)和內核
  • BasicObject(實例方法)

紅寶石找到實例方法Module#constants

Module.constants被調用時,紅寶石看着

  • Module"Object"BasicObject"(singleton方法)
  • Class(實例方法)
  • Module(實例方法)
  • Object(實例方法)和內核
  • BasicObject(實例方法)

正如馬克所說,這一次,Ruby在上發現了singleton/class方法。

模塊定義了一個影響實例方法的單例方法。單例方法返回所有已知的常量,而實例方法返回當前類及其祖先中定義的常量。

相關問題