Method#unbind
返回对该方法的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()
类似。但是,要绑定方法的对象必须属于同一类。
我能想到的唯一一个应用程序是,如果解除绑定方法,丢失原始实现(重新定义原始或单例类中的方法),然后重新绑定并调用它。
答案 0 :(得分:2)
我总结了迄今为止我发现的好用途。但是,它们都没有使用unbind
。
首先,使用旧的实现覆盖方法。 Source,感谢@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
其次,从层次结构中调用方法的另一个实现。 Source。
帖子中给出的非常实用的例子是,在调试过程中,您经常需要找到定义方法的位置。一般来说,您可以通过以下方式实现:
method(:foo).source_location
但是,如果当前实例实现了method
方法,那将无法工作,就像ActionDispatch::Request
的情况一样。在这种情况下,你可以这样做:
Kernel.instance_method(:method).bind(self).call(:foo).source_location
答案 1 :(得分:0)
Method和UnboundMethod类型期望绑定目标必须是引用该方法的原始类的子类。但是,方法实现了#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