2013-01-03 167 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这样,以及添加方法的对象只针对一个块的使用寿命。

相关问题