其他人已经告诉你要子类化。但是要回答您的字面问题,我们将涉及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_method
或UnboundMethod#bind
不能将方法绑定到不兼容的对象。这不能被重新定义之类的技巧所欺骗#kind_of?
,必须在本机代码中欺骗 CLASS_OF() 函数......
在可用的 gem 中,Sourcify、RubyParser和Sorcerer很有趣。(谢谢,@Casper。)使用这些,理论上可以通过#eval
-ling 提取的方法源在不兼容的对象之间移植代码。很长的路要走,这种技术仍然无法实现可靠的方法传输,因为只要源在运行时不可用(例如,自修改源),它就会失败。