Ruby 将一个类中的方法分配给另一个类的实例
正如标题所示,我想将在一个类上定义的所有实例方法分配给另一个类。我知道在我可以得到我想从Ruby 将一个类中的方法分配给另一个类的实例,ruby,metaprogramming,Ruby,Metaprogramming,正如标题所示,我想将在一个类上定义的所有实例方法分配给另一个类。我知道在我可以得到我想从ClassA复制到ClassB的方法列表,如下所示: ClassA.instance_methods(false) ClassA.instance_methods(false).each do |method_name| ClassB.method_define(method_name, [body here??]) end um = Object.instance_method :kokot #=&
ClassA
复制到ClassB
的方法列表,如下所示:
ClassA.instance_methods(false)
ClassA.instance_methods(false).each do |method_name|
ClassB.method_define(method_name, [body here??])
end
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
我想我可以在ClassB
上这样定义它们:
ClassA.instance_methods(false)
ClassA.instance_methods(false).each do |method_name|
ClassB.method_define(method_name, [body here??])
end
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
有没有一种方法可以获得相应的方法体,如果有,这个方法是否有效?如果没有,是否有办法做到这一点?您可能需要的是混入: 取自
在这种情况下,
classB
应该继承classA
其他人已经告诉过您要子类化。但为了回答您的字面问题,我们将涉及UnboundMethod
对象:
class Object
def kokot; 'kokot' end
end
o = Object.new
o.kokot
#=> kokot
3.kokot
#=> kokot
到目前为止还不错。现在,让我们重新定义Numeric
上的kokokot
方法:
class Numeric
def kokot; 'pica' end
end
o.kokot
#=> kokot
3.kokot
#=> pica
但是如果我们决定,新的kokot
方法对于数值计算来说是很好的,但是仅仅复数应该继续使用旧的kokot
方法。我们可以这样做:
ClassA.instance_methods(false)
ClassA.instance_methods(false).each do |method_name|
ClassB.method_define(method_name, [body here??])
end
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
返回nil
。在Ruby 2.0中,RubyVM
类具有方法#反汇编
:
RubyVM::InstructionSequence.disassemble( um )
#=> ( program listing goes here )
无论如何,Ruby字节码看起来并不漂亮。回到您最初的需要,甚至#define#u method
或UnboundMethod#bind
都不能将方法绑定到不兼容的对象。这不能被诸如重新定义#kind_of?
之类的技巧所欺骗,必须在本机代码中欺骗CLASS_of()函数
从现有的宝石,和感兴趣的。(谢谢,@Casper。)使用这些,理论上可以通过
#eval
-ling提取方法源在不兼容的对象之间移植代码。从长远来看,这种技术仍然无法实现可实现的方法传输,因为每当源代码在运行时不可用时(例如自修改源代码),它就会失败。在ruby 2.0中,您可以使用模块。马茨明确表示
但是您可以使用模块中的实例方法
ModuleA.instance_methods(false).each do |name|
meth = ModuleA.instance_method(name)
ClassB.send(:define_method, name, meth)
end
define_方法
是一种私有方法,因此在此处使用send
但为什么要这样做呢?只包括模块
如果只想将行为应用于对象,可以从任何模块解除方法绑定,并将其绑定到任何对象
ModuleA.instance_method(:something).bind(some_object).call(args)
如果这是您想要的,请查看
铸造,一个类似这样的方法,以及仅在块的生命周期内向对象添加方法。为什么要这样做?你为什么不能使用mix-ins/modules来完成这个任务?@John:我不认为OP是一个不理解子类化概念的noob。你为什么不直截了当地回答他的问题?你的代码与你的标题相矛盾。您希望ClassA和ClassB(不是它的单个实例)共享相同的方法。John Naegle的答案是正确的:将ClassA的所有实例方法移动到一个模块中,然后将该模块包含到两个类中。在我看来,这是正确的答案:)