2012-11-15 45 views
6

我有一個模塊讓我打電話「計算器」,我想包括在一個類「產品」。計算器將擴展「產品」,將產品複製到產品上。其中一種方法是「記憶」。這個想法是我可以這樣做:如何動態定義類方法的別名方法?

module Calculator 
    def self.extended(base) 
    base.memoize :foo_bar 
    end 
end 

爲了記憶方法(特別是類方法):foo_bar。在memoize的內部,我調用方法「alias_method」,它嘗試將一個類方法別名爲不同的名稱(這裏是:foo_bar)。這失敗了。 memoize的看起來像:

module Calculator (the extended module) 
    def memoize(name) 
    alias_method "memoized_#{name}", name 
    end 
end 

當這是通過memoize的叫:foo_bar這樣的名稱,該alias_method線踢一個錯誤,說產品有沒有方法「名」 ..我的理解是,這是因爲alias_method將嘗試別名實例方法不是類的方法。(我不知道爲什麼,但確定沒有什麼大不了的)..

我可以重新打開eigenclass像這樣

module Calculator 
    def memoize(name) 
    class << self 
     alias_method "memoized_#{name}", name 
    end 
    end 
end 

這會工作,但名字不能用於範圍類< < s精靈的定義。人們提到使用self.class_eval和self.instance_eval,但這些都不起作用..我想我的蛋糕也吃了它..我怎麼能保持alias_method動態,但在class_methods上使用它?

回答

3

所以才瞭解到,這將這樣的伎倆:

module Calculator 
    def memoize 
    define_singleton_method(name, method(name)) 
    end 
end 

然後當計算器被納入產品會定義單方法,因爲我需要的。我仍然不知道爲什麼alias_method只需要在實例方法上工作..我不知道爲什麼class_eval或instance_eval沒有解決問題..但至少我有一個解決方案..

3

如果你在include/extend之前把實例方法設置爲別名?如果您在類名後面加上擴展名,實例方法將不會被定義。

module Foo 
    def self.extended(base) 
    base.memoize :flavor 
    end 

    def memoize(name) 
    alias_method "memoized_#{name}", name 
    end 
end 

class Bar 
    def flavor 
    puts "Orange" 
    end 

    extend Foo 
end 

if __FILE__==$0 
    b = Bar.new 
    b.memoized_flavor #=> Orange 
end 
+0

雖然好的想法實際上並不是這種情況,因爲被混淆的方法在模塊中被擴展並且在試圖混疊之前被擴展。雖然偉大的想法。 – Inc1982