Ruby的方法解除绑定机制有什么意义? [英] What is the point of Ruby's method unbinding mechanism?
问题描述
Method#unbind
返回一个UnboundMethod
对方法的引用,以后可以使用 UnboundMethod#bind
.
Method#unbind
returns an UnboundMethod
reference to the method, which can later be bound to another object using 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()
类似.但是,您要绑定方法的对象必须属于同一类.
Initially, I thought this is incredibly awesome, because I expected it would work similarly to JavaScript's Function.prototype.call()
/Function.prototype.apply()
. However, the object to which you want to bind the method must be of the same class.
我唯一想到的应用程序是:取消绑定方法,丢失原始实现(在原始类或单例类中重新定义该方法),然后重新绑定并调用它.
The only application I can think of is if you unbind a method, lose the original implementation (redefine the method in the original or singleton class) and then rebind and call it.
推荐答案
我将总结到目前为止所发现的良好用途.都不使用unbind
.
I'll summarize the good uses I found so far. Neither uses unbind
though.
首先,使用旧的实现覆盖方法. 来源,感谢@WandMaker.
Firstly, overwriting a method, using the old implementation. Source, thanks to @WandMaker.
假设您要执行以下操作:
Let say you want to do something like this:
class Foo
alias old_bar bar
def bar
old_bar
some_additional_processing
end
end
这将起作用,但会留下old_bar
,这是不希望的.相反,可以这样做:
This will work, but will leave behind old_bar
, which is not something desirable. Instead, one could do:
class Foo
old_bar = instance_method(:bar)
define_method(:bar) do
old_bar.bind(self).call
some_additional_processing
end
end
其次,从层次结构中调用方法的另一种实现. 帖子中给出的一个非常实际的示例是,在调试过程中,您经常想找到定义方法的位置.一般来说,您可以通过以下方式做到这一点:
The very practical example given in the post was that often times during debugging, you want to find where a method was defined. Generally speaking you can do that by:
method(:foo).source_location
但是,如果当前实例实现method
方法,则此方法将无效,例如 ActionDispatch::Request
.在这种情况下,您可以执行以下操作:
However, this won't work if the current instance implements a method
method, like is the case with ActionDispatch::Request
. In that case you can do:
Kernel.instance_method(:method).bind(self).call(:foo).source_location
这篇关于Ruby的方法解除绑定机制有什么意义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!