2013-01-03 166 views
3

正如標題所示,我想將所有在一個類上定義的實例方法分配給另一個類。我知道我能得到的,我想從ClassA複製到ClassB這樣的方法列表:將一個類的方法分配給另一個類的另一個實例

ClassA.instance_methods(false) 

而且我認爲我可以定義他們ClassB這樣的:

ClassA.instance_methods(false).each do |method_name| 
    ClassB.method_define(method_name, [body here??]) 
end 

是有一種方法可以獲得相應的方法體,如果是的話,這個方法會起作用嗎?如果沒有,是否有辦法做到這一點?

+5

你爲什麼要這樣做?任何你不能使用混合模塊/模塊來完成這個任務的原因? –

+2

@John:我不認爲OP是一個不理解子類概念的noob。你爲什麼不從字面上理解他的問題? –

+0

您的代碼與您的標題相矛盾。你希望ClassA和ClassB(不是它的一個實例)共享相同的方法。 John Naegle的回答是正確的:將ClassA的所有實例方法移動到一個模塊中,然後將這個模塊包含到這兩個類中。 – BernardK

回答

3

好像你可能想要的是搭配的插件:

http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html

module Debug 
    def whoAmI? 
    "#{self.type.name} (\##{self.id}): #{self.to_s}" 
    end 
end 
class Phonograph 
    include Debug 
    # ... 
end 
class EightTrack 
    include Debug 
    # ... 
end 
ph = Phonograph.new("West End Blues") 
et = EightTrack.new("Surrealistic Pillow") 
ph.whoAmI? » "Phonograph (#537766170): West End Blues" 
et.whoAmI? » "EightTrack (#537765860): Surrealistic Pillow" 
+0

對我來說似乎是合適的答案:) – BernardK

0

兩者在這種情況下,classB要繼承classA

8

其他人已告訴你的子類。但是,爲了回答你的問題的文字,我們會捲入與UnboundMethod對象:

class Object 
    def kokot; 'kokot' end 
end 

o = Object.new 
o.kokot 
#=> kokot 

3.kokot 
#=> kokot 

到目前爲止好。現在,讓我們重新定義kokot方法上Numeric

class Numeric 
    def kokot; 'pica' end 
end 

o.kokot 
#=> kokot 
3.kokot 
#=> pica 

但如果我們決定,新kokot方法是偉大的數字,但只是複數應繼續使用舊kokot方法。我們可以這樣做:

um = Object.instance_method :kokot 
#=> #<UnboundMethod: Object#kokot> 
Complex(2, 3).kokot # gives the redefined kokot method 
#=> pica 
Complex.module_exec { define_method :kokot, um } 
# Now we've just bound the old kokot to Complex 
Complex(2, 3).kokot 
#=> kokot 

總之,有一種方法可以在相關類中「複製和粘貼」方法。要求目標是未綁定方法源的子類。方法#source_location顯示該文件,並在那裏#kokot已經定義行:

um.source_location 
#=> ["(irb)", 2] 

對於內置的方法,#source_location返回nil。在Ruby 2.0,RubyVM類有方法#disassemble

RubyVM::InstructionSequence.disassemble(um) 
#=> (program listing goes here) 

在任何情況下,Ruby的字節碼是不是看起來很美。回到您的原始需求,甚至不是#define_methodUnboundMethod#bind都可以將方法綁定到不兼容的對象。這不能用的技巧,比如重新定義#kind_of?被騙了,一會要騙CLASS_OF在本機代碼()函數...

從可用的寶石,SourcifyRubyParserSorcerer感興趣。 (謝謝,@Casper。)使用這些,理論上可以通過#eval -ling提取的方法源在不兼容的對象之間移植代碼。很長的路要走,這種技術仍然不能實現可靠的方法轉移,因爲只要源在運行時不可用(例如,自修改源),它就會失敗。

0

在ruby 2.0中,您可以使用模塊。馬茨明確forbade this behavior from classes

但是,您可以使用模塊中的instance_methods。

ModuleA.instance_methods(false).each do |name| 
    meth = ModuleA.instance_method(name) 
    ClassB.send(:define_method, name, meth) 
end 

define_method是一個私有方法,所以這就是爲什麼你使用send這裏。

但是爲什麼要這樣做呢?只需包含該模塊。

如果您只想將行爲應用於對象,則可以從任何模塊中解除綁定方法並將其綁定到任何對象。

ModuleA.instance_method(:something).bind(some_object).call(args) 

如果這是你想要什麼,看看casting,一個gem that adds a convenience to doing delegation這樣,以及添加方法的對象只針對一個塊的使用壽命。

相關問題