Ruby的方法解绑机制有什么意义?

Method#unbind UnboundMethod返回对该方法的UnboundMethod引用,该引用稍后可以使用UnboundMethod#bind绑定到另一个对象。

 class Foo attr_reader :baz def initialize(baz) @baz = baz end end class Bar def initialize(baz) @baz = baz end end f = Foo.new(:test1) g = Foo.new(:test2) h = Bar.new(:test3) f.method(:baz).unbind.bind(g).call # => :test2 f.method(:baz).unbind.bind(h).call # => TypeError: bind argument must be an instance of Foo 

最初,我认为这非常棒,因为我预计它的工作方式与JavaScript的Function.prototype.call() / Function.prototype.apply()类似。 但是,要将方法绑定到的对象必须属于同一个类

我能想到的唯一应用是,如果解除绑定方法,丢失原始实现(重新定义原始或单例类中的方法),然后重新绑定并调用它。

我将总结迄今为止我发现的好用途。 虽然没有使用unbind


首先,使用旧的实现覆盖方法。 来源 ,感谢@WandMaker。

假设你想做这样的事情:

 class Foo alias old_bar bar def bar old_bar some_additional_processing end end 

这将有效,但会留下old_bar ,这不是一个可取的东西。 相反,人们可以这样做:

 class Foo old_bar = instance_method(:bar) define_method(:bar) do old_bar.bind(self).call some_additional_processing end end 

其次,从层次结构中调用方法的另一个实现。 来源 。

post中给出的非常实用的例子是,在调试过程中,您经常需要找到定义方法的位置。 一般来说,你可以这样做:

 method(:foo).source_location 

但是,如果当前实例实现method方法,这将无法工作,就像ActionDispatch::Request的情况一样。 在这种情况下,你可以这样做:

 Kernel.instance_method(:method).bind(self).call(:foo).source_location 

Method和UnboundMethod类型期望绑定目标必须是引用该方法的原始类的子类。 但是,Method已经实现了#to_proc方法,因此您可以摆脱“相同的类类型”约束。

您必须使用#send方法,因为#define_method是私有的(您不能直接调用它)。

 class A def hoge ; "hoge" ; end end class B ; end hoge = A.new.method(:hoge) B.send(:define_method, :hoge_in_b, &hoge) #converting to proc b = B.new puts b.hoge_in_b