Ruby元编程读书笔记十一
Methods Revisited
最后一个可调用对象是 方法,它跟 lambda 一样不过是可调用的对象而已:
class MyClass
def initialize(value)
@x = value
end
def my_method
@x
end
end
object = MyClass.new(1)
m = object.method :my_method
m.call #=> 1
通过调用 Object#method() 方法可以获得一个用 Method 对象表示的方法,以后可以用 Method#call() 对它进行调用。Method 对象类似于 lambda,但有一个重要的区别: lambda 在定义它的作用域中执行(它是一个闭包),而 Method 对象会在它自身所在对象的作用域中执行。
可以用 Method#unbind() 方法把一个方法跟它所绑定的对象相分离,该方法再返回一个 UnboundMethod 对象。UnboundMethod 对象不能被执行,但能被绑定到一个对象上,使之再次成为一个 Method 对象。
unbound = m.unbind
another_object = MyClass.new(2)
m = unbound.bind(another_object)
m.call #=> 2
这种技术只有在 another_object 与原先这个方法的对象属于同一个类时才起作用,否则会得到一个异常。
可以调用 Method#to_proc() 方法把 Method 对象转换为 Proc 对象,也可以使用 define_method() 方法把块转换为方法(我们之前用过)。
Callable Objects Wrap-Up
可调用对象是可以执行的代码片段,而且它们有自己的作用域。可调用对象可以有以下几种方式:
-
块(虽然它们不是真正的对象,但是它们是可调用的):在定义它们的作用域中执行。
-
proc:Proc 类的对象,跟块一样,它们也在定义自身的作用域中执行。
-
lambda:也是 Proc 类的对象,但是它跟普通的 proc 有细微的差别。它跟块和 proc 一样都是闭包,因此也在定义自身的作用域中执行。
-
方法:绑定于对象,在所绑定对象的作用域中执行。它们也可以与这个作用域解除绑定,再重新绑定到另一个对象的作用域上。
不同种类的可调用对象有细微的区别。在方法和 lambda 中,return 语句从可调用对象中返回。在块和 proc 中,return 语句从定义可调用对象的原始上下文中返回。另外,不同的可调用对象对传入参数数目不符合有不同的反应。其中方法的处理方式最严格, lambda 同样严格,而 proc 和块则要宽松一些。
尽管有这些区别,还是可以将一种可调用对象转换为另外一种可调用对象的,实现这样功能的方法包括 Proc.new() 方法、Method#to_proc() 方法和 & 操作符。