在Ruby中绑定/解除绑定方法的目的是什么? [英] What the purpose of bind/unbind methods in Ruby?

查看:106
本文介绍了在Ruby中绑定/解除绑定方法的目的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

拥有Method#unbindUnboundMethod#bind的目的是什么?

据我所知,方法是可调用对象,例如proc和lambda,除了方法绑定到其接收者的作用域之外:

From what I gather, methods are callable objects like procs and lambdas, except that methods are bound to the scope of their receiver:

class SomeClass
  def a_method; puts "from SomeClass"; end
end

s = SomeClass.new
s.a_method # => "from SomeClass"

如果我在SomeClass的上下文中,或者我有SomeClass的对象,则可以调用a_method.通过将方法提取为Method对象,可以使其成为可调用对象,但在此示例中,该方法仍绑定到类SomeClass的对象:

I can call a_method if I'm within the context of SomeClass or if I have an object of SomeClass. I can make it a callable object by extracting the method as a Method object, yet it's still bound to an object of class SomeClass in this example:

m = s.method :a_method
m.class # => Method
m.owner # => SomeClass
m.call # => "from SomeClass"

为什么我要从其接收者中unbind一个方法?也许我可以将其传递给bind或其他对象,以为其提供新的上下文,也许我可以使用完全不同的对象来调用此方法而无需继承,但是除非将其绑定到对象,否则我将无法对其进行任何操作或将其转换为Proc对象(实际上是lambda,因为方法和lambda有点相似):

Why would I want to unbind a method from its receiver? Maybe I can pass this around or bind it to a different object giving it new context, maybe I can have a completely different object call this method without inheritance, but I can't do anything with it unless I bind it to an object of its original class or I convert it to a Proc object (really a lambda, since methods and lambdas are somewhat similar):

# 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"

我可以将方法对象转换为proc并可能对其进行处理:

I could convert the method object into a proc and maybe do something with it:

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"

这样做的目的是什么?像这样的东西在现实世界中有什么应用?

What is the purpose of doing this? What are the real world applications for something like this?

推荐答案

对于元编程确实非常有用.假设您想知道SomeClass#method源代码的位置.如果可以生成SomeClass的实例,则可以在该SomeClass实例上创建它的(绑定)方法实例,在该实例上可以调用各种方法来研究该方法的某些元数据.但是,如果您不知道SomeClass#new的方法签名,或者如果SomeClass的构造方法被命名为SomeClass#new以外的名称,该怎么办?仅安全地创建SomeClass的实例可能很困难.这就是未绑定方法派上用场的地方.不必担心类的特定实例或如何创建实例,您只需执行SomeClass.instance_method(:a_method)(这是一个未绑定的方法),然后在其上调用source_location来研究定义的位置:

It is indeed useful for metaprogramming. Suppose you want to know the location of the source code for SomeClass#method. If you can generate an instance of SomeClass, then you can create a (bound) method instance of it on that SomeClass instance, on which you can call various methods to investigate some meta-data of the method. But what if you did not know the method signature of SomeClass#new, or what if SomeClass's constructor method was named other than SomeClass#new? Just safely creating an instance of SomeClass can be difficult. That is where unbound method comes in handy. Without bothering with a particular instance of the class, or with how to create an instance, you can simply do SomeClass.instance_method(:a_method) (which is an unbound method), then call source_location on it to investigate the location of the definition:

unbound = SomeClass.instance_method(:a_method)
puts unbound.source_location

那么在实际应用中什么时候需要这种元编程?一个示例是在创建具有用于方法查找功能的IDE时.

And when would this kind of metaprogramming be necessary in the real world applications? One example is when you are creating an IDE with functions for method lookup.

这篇关于在Ruby中绑定/解除绑定方法的目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆