2014-04-12 66 views
0

我有這個元編程方案,觸及Ruby的一些更好的功能,我不太清楚如何解決。如何在Ruby中的子類中動態定義的方法調用super?

每個人都可以輕鬆編程下面的例子來完成它應該做的事情,但我需要在超類和派生子類中動態地定義方法。

在這個例子中,基類有一個動態定義的方法:foo和cource它暴露給子類B.但是,當我在子類B的一個實例上調用:foo時,我在動態定義的方法中檢測,我似乎無法從B類實例傳遞給A類實例,而Cource類是我想要的。

奇怪的紅寶石分類定義的子類的方法也是這樣,但無論如何,這就是我正在嘗試解決的問題。

任何線索?

class A 
    def self.some_method method,*_params 
    puts "#{name}: defining #{method}" 
    define_method method do |*args| 
     puts "#{self.class.name}: called #{method}" 
     super *args unless self.class.instance_methods(false).include?(method) 
    end 
    end 
end 

class B < A 
end 

A.some_method :foo 

B.new.foo 

輸出

A: defining foo 
B: called foo 
NoMethodError: super: no superclass method `foo' for #<B:0x007f9eab85bfa0> 
+0

BTW:我試圖避免的method_missing。 – patrick

回答

3

我覺得這是你的邏輯缺陷。

您將動態方法定義爲超類A。調用B.new.fooB中找不到方法,因此它沿着繼承線。它在A中找到foo方法,因此它使用該方法。
這意味着,不需要在所有

super *args unless self.class.instance_methods(false).include?(method)
一部分。

我看到它的方式,經典的方法繼承是你所需要的!

+0

那麼,少量輸入就足以讓我意識到我的需要是知道什麼類定義訪問超類變量的方法,並且可以通過以下方式輕鬆完成:current = self.class; current = current.superclass while current.instance_methods(false).include?(method) 因此,感謝您給我的大理石一個微調! – patrick

+0

我明白了......你是否考慮過包含共享方法的特殊模塊而不是類繼承?這可能被證明是一種更靈活的做事方式。 – xlembouras

+0

是的,但我有一個相當細緻的需求。 (只要看看可可寶石,你就會知道)。當我們說話時重新定義架構。 – patrick

0

確實有瑕疵的邏輯。當然需要訪問定義了方法的類,而超級不能幫助你。

以下是解決問題的辦法:

class A 
    def self.some_method method,*_params 
    puts "#{name}: defining #{method}" 
    define_method method do |*args| 
     puts "#{self.class.name}: called #{method}" 

     klass = self.class 
     klass = klass.superclass while !klass.instance_methods(false).include?(method) 

     # klass is now where the instance method is defined 
     # and you can now access its class variables etc. 
     puts "#{klass.name}: has method #{method}" 
    end 
    end 
end 

class B < A 
end 

A.some_method :foo 

B.new.foo 

輸出

A: defining foo 
B: called foo 
A: has method foo 
相關問題