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的所有实例方法移动到一个模块中,然后将该模块包含到两个类中。在我看来,这是正确的答案:)