Ruby中的instance_eavl和class_eval
ruby元编程中的instance_eavl和class_eval简单介绍
第二次看Ruby元编程这本书,感觉里面能学到的东西很多,但是很容易忘记,所以把一些想法写下来,以备后用。
instance_eval
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
首先,我们分析上面代码:
- 当我们实例化一个类时,我们可以通过instance_eval来访问到该类的实例方法,所以我们可以看到
self
返回一个对象,@v
返回1 - 由于block是一个闭包,所以在运行的时候,可以访问局部变量
v
,而且能访问局部变量@v,这种情况,我们把他叫做上下文探针
,它就像是一个深入到对象中的代码片段,对其进行操作。 - 当我们在instance_eval块里面定义方法是,由于self为当前对象,所以
def
关键子打开的作用域门为self,即定义的方法只有obj可以访问,我们称它为单件方法。
- 当我们实例化一个类时,我们可以通过instance_eval来访问到该类的实例方法,所以我们可以看到
然后,我们总结instance_eval的作用:
- instance_eval的调用者必须是一个实例
- 改变当前block的接受者为self,因此它可以访问接受者的私有方法和实例变量
- 可以在block内使用单件方法
最后,我们还发现,可以用instance_eavl来定义类方法
1 2 3 4 5 6 7 8 9 |
|
class_eval(又名module_eval)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
- 分析上面代码,我们可以发现
class_eval
和instance_eval
的区别:class_eval
的调用对象必须是一个类class_eval
block里面的self为类本身(实际上是重新打开了该类,相当于关键字class
) *class_eval
定义的方法为类的实例方法(instance_eval是单件方法)
总结:什么时候用class_eval
和instance_eval
如果打开的对象不是类,则使用instance_eval
,如果想打开一个类定义并且用def
定义实例方法,则选择class_eval
根据调用者来决定
*根据你的意图来决定