Ruby 中 bind/unbind 方法的目的是什么?
What the purpose of bind/unbind methods in Ruby?
Method#unbind
和 UnboundMethod#bind
的目的是什么?
据我所知,方法是像 procs 和 lambdas 这样的可调用对象,除了方法绑定到它们的接收者的范围之外:
class SomeClass
def a_method; puts "from SomeClass"; end
end
s = SomeClass.new
s.a_method # => "from SomeClass"
如果我在 SomeClass
的上下文中或者我有一个 SomeClass
的对象,我可以调用 a_method
。我可以通过将方法提取为 Method
对象使其成为可调用对象,但在本例中它仍然绑定到 class SomeClass
的对象:
m = s.method :a_method
m.class # => Method
m.owner # => SomeClass
m.call # => "from SomeClass"
为什么我要 unbind
从它的接收者那里得到一个方法?也许我可以将它或 bind
传递给另一个对象,给它新的上下文,也许我可以让一个完全不同的对象在没有继承的情况下调用这个方法,但我不能用它做任何事情,除非我将它绑定到其原始 class 的对象或我将其转换为 Proc
对象(实际上是 lambda,因为方法和 lambda 有点相似):
# Module#instance_method gives me an UnboundMethod
ub = SomeClass.instance_method :a_method
ub.class # -> UnboundMethod
# now I can't make any calls
ub.call # -> NoMethod Error, undefined method 'call'
class AnotherClass; end
a = AnotherClass.new
b = ub.bind(a) # -> TypeError: bind argument must be an instance of SomeClass
b = ub.bind(SomeClass.new).call # -> "from SomeClass"
我可以将方法对象转换成一个过程,也许可以用它做点什么:
AnotherClass.class_eval do
# I can access m becausec this block is evaluated in the same
# scope it's defined, so I can grab m ;)
define_method(:method_from_some_class, m.to_proc)
end
AnotherClass.instance_methods(false) # -> [:method_from_some_class]
a.method_from_some_class # -> "from SomeClass"
这样做的目的是什么?像这样的东西在现实世界中有哪些应用?
对元编程确实有用。假设您想知道 SomeClass#method
的源代码位置。如果您可以生成 SomeClass
的实例,那么您可以在该 SomeClass
实例上创建它的(绑定)方法实例,您可以在该实例上调用各种方法来调查某些 meta-data方法。但是,如果您不知道 SomeClass#new
的方法签名怎么办,或者如果 SomeClass
的构造方法的名称不是 SomeClass#new
怎么办?只是安全地创建一个 SomeClass
的实例可能很困难。这就是未绑定方法派上用场的地方。无需考虑 class 的特定实例或如何创建实例,您只需执行 SomeClass.instance_method(:a_method)
(这是一个未绑定的方法),然后调用 source_location
进行调查定义位置:
unbound = SomeClass.instance_method(:a_method)
puts unbound.source_location
在现实世界的应用程序中什么时候需要这种元编程?一个例子是当您创建一个带有方法查找函数的 IDE 时。
Method#unbind
和 UnboundMethod#bind
的目的是什么?
据我所知,方法是像 procs 和 lambdas 这样的可调用对象,除了方法绑定到它们的接收者的范围之外:
class SomeClass
def a_method; puts "from SomeClass"; end
end
s = SomeClass.new
s.a_method # => "from SomeClass"
如果我在 SomeClass
的上下文中或者我有一个 SomeClass
的对象,我可以调用 a_method
。我可以通过将方法提取为 Method
对象使其成为可调用对象,但在本例中它仍然绑定到 class SomeClass
的对象:
m = s.method :a_method
m.class # => Method
m.owner # => SomeClass
m.call # => "from SomeClass"
为什么我要 unbind
从它的接收者那里得到一个方法?也许我可以将它或 bind
传递给另一个对象,给它新的上下文,也许我可以让一个完全不同的对象在没有继承的情况下调用这个方法,但我不能用它做任何事情,除非我将它绑定到其原始 class 的对象或我将其转换为 Proc
对象(实际上是 lambda,因为方法和 lambda 有点相似):
# Module#instance_method gives me an UnboundMethod
ub = SomeClass.instance_method :a_method
ub.class # -> UnboundMethod
# now I can't make any calls
ub.call # -> NoMethod Error, undefined method 'call'
class AnotherClass; end
a = AnotherClass.new
b = ub.bind(a) # -> TypeError: bind argument must be an instance of SomeClass
b = ub.bind(SomeClass.new).call # -> "from SomeClass"
我可以将方法对象转换成一个过程,也许可以用它做点什么:
AnotherClass.class_eval do
# I can access m becausec this block is evaluated in the same
# scope it's defined, so I can grab m ;)
define_method(:method_from_some_class, m.to_proc)
end
AnotherClass.instance_methods(false) # -> [:method_from_some_class]
a.method_from_some_class # -> "from SomeClass"
这样做的目的是什么?像这样的东西在现实世界中有哪些应用?
对元编程确实有用。假设您想知道 SomeClass#method
的源代码位置。如果您可以生成 SomeClass
的实例,那么您可以在该 SomeClass
实例上创建它的(绑定)方法实例,您可以在该实例上调用各种方法来调查某些 meta-data方法。但是,如果您不知道 SomeClass#new
的方法签名怎么办,或者如果 SomeClass
的构造方法的名称不是 SomeClass#new
怎么办?只是安全地创建一个 SomeClass
的实例可能很困难。这就是未绑定方法派上用场的地方。无需考虑 class 的特定实例或如何创建实例,您只需执行 SomeClass.instance_method(:a_method)
(这是一个未绑定的方法),然后调用 source_location
进行调查定义位置:
unbound = SomeClass.instance_method(:a_method)
puts unbound.source_location
在现实世界的应用程序中什么时候需要这种元编程?一个例子是当您创建一个带有方法查找函数的 IDE 时。