Metaprogramming Ruby
第一章,object model
class与module
- class是object,class name是定数。object的instance value住在object里面,object的method住在class里面。
- class只是一个拥有allocate, new, superclass这三个函数的module。那么什么时候用class,什么时候用module呢?一般当要被include的时候用module(或者当作namespace使用的时候),要生成或者继承的时候使用class。
Kernel module
Object Class include 了 Kernel 这个module,Kernel module里面有print()之类的method,因此可以直接在任何地方呼叫print(),如果展开Kernel,在里面定义自己的method的话,也可以在任何地方呼叫自己的method。
private真正的意义
用private关键词定义method有一个规则,那就是不可以指定receiver(接收对象),比如
然而呼叫一般的method也有一个规则,就是除了自己,呼叫任何method都必须明确制定receiver。private method也要遵守这个规则,就是说private method只可以呼叫自己。那么从superclass继承的private method呼叫么?答案当然是可以,因为继承的class里面也可以不用明确的制定receiver的。
定数
module或者class可以看成dirictory,定数可以看成file
为了避免自己的class名字跟其他library里面的class名字冲突,可以用module来定义自己的class。比如
第二章,method
重复code的排除
动态呼叫method
动态定义method
define_method
method_missing()
obj.mymethod的时候会先向右在obj的class里查找mymethod,如果class里面没有就向上查找superclass,然后一直向上查找到BasicObject,如果BasicObject里面也没有的话就会呼叫obj的method_missing,如果重新定义methodmissing的话就可以呼叫没有定义过的method,这个method就叫做__ghost method__
与method_missing一样,Module#const_missing是Module下面的method
Module#undef_method(), Module#remove_method()
undef_method会删除class里已经继承这个class里的所有method,remove_method则只会删除receiver里面的method
第三章,block
Kernel#block_given?()
闭包
单独的block code是无法执行的,要执行block还要有local variable,instance variable,self等环境,这个环境在ruby里面也叫做束缚(翻译的可能不太准确),block由code和束缚组成。
这个block取得了x = hello这个束缚。这个特性也被称作闭包。
scope gata
ruby切换scope,然后打开一个新的scope有3个地方,分别是:1,定义class。2,定义module。3,呼叫method, 也就是__class, module, def__这三个关键字。那么如何突破scope,传递束缚呢?其实很简单,定义class,或者定义method的时候不用这3个关键字就可以了,比如定义class的时候可以使用Class.new,定义method的时候可以用difine_method。可以看下面这个例子
下面这个例子是共享scope
instance_eval()
在block里面评价object的context(上下文)
cleanroom
callable object
Proc
block转换成Proc,在block前面加上&修饰符就可以了。block通过yield来呼叫,而Proc通过call来呼叫。Proc转换成block,也是在Proc前面加上&就可以了。在1.9里面,Proc通过Proc.new或者Kernel#proc()来创建。
lambda与Proc的区别
lambda通过Kernel#lambda()或者 ー>(将来是否可以用还不知道)来创建,lambda像是一个匿名函数,因此在return的时候,lambda会跳出block,而Proc则会跳出block所在的method。另外一方面,lambda在传递引数的时候比较严格,而Proc则比较宽松,比如
Method object
Method通过Object#method()来取得,通过Method#call()来呼叫。Method跟lambda基本一样,不一样的是lambda在scope里面评价,而Method在附属的object里面评价。
第四章 class的定义
class
class_eval(),别名module_eval()
在block里面评价Class的context(上下文)
class instance value
class value则是@@var,一般不建议使用
class的名字只是单纯的__定数__。
特异method
这里的title?就是str object的特异method
class method 就是 class的特异method
特异class
特异method就住在特异class里面。
大统一理论:1,object只有一种,那就是通常的object或者module。2,module只有一种,那就是module或者class或者特异class或者proxy class。3,method只有一种,就住在module(大部分是class)里面。4,所有的object都拥有class,这个class可能是一般的class或者特异class。5,所有的class都有super class(BasicObject除外),所有的class都继承自BasicObject。6,object的特异class的superclass是object的class。class的特异class的superclass是class的superclas的特异class。7,method呼叫的时候先向右一步找他的class,再向上找superclass。
alias
第五章,code来写code
Kernel#eval
instance_eval也可以接收文字,如