他の人はすでにサブクラス化するように言っています。しかし、あなたの文字通りの質問に答えるために、私たちは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
抽出されたメソッドソースを介して互換性のないオブジェクト間でコードを移植できます。長い道のりですが、実行時にソースが利用できない場合 (自己変更ソースなど) は常に失敗するため、この手法は実現可能なメソッド転送にはまだ不十分です。