和其它的面向对象语言类似,ruby的类方法也分为class method 和 instance method, module和class具有相当大程度的相似性, 但是用于重用module中定义的方法时( 同样也有 class method 和 instance method 之分 ),又有一些微妙的差异。
class method定义
遵循perl的设计哲学,ruby中的class method也有三种方法,分别如下:
- 类内define法,需要在 method name 之前显示加上 self 指明这是个属于 class 的方法:
1 2 3 4 5 6 7 |
|
2. Append 法,通过 << 添加到 self,如下:
1 2 3 4 5 6 7 8 9 10 |
|
3. 类外定义,和定义一个普通函数的方法类似,但是指明了 class name, 可以用于方便的向已定义好的类中添加 class method:
1 2 3 4 5 6 |
|
include/extend
当 module 中的方法被新的类通过MIXIN方法包含的时候,module中定义的方法在新的类中是被定位为 class method 还是定义为 instance method? 答案取决于包含 module 的方法,这里是一段测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
运行结果如下:
1 2 3 |
|
这里的输出表明:
- 以 include 方法包含的 module 其定义的方法会被解析为 instance method, 即 include 包含 instance methods
- 以 extend 方法包含的 module 其定义的方法会被解析为 class method, 即 extend 扩展 class methods
扩展 module 的习惯用法
尽管 include 和 extend 分别用于扩展 instance method 和 class method, 我们还是可以采用一种惯用法来同时包含一个module的 instance methods 和 class methods. Rails 就利用了这种惯用法: 用 include 同时添加 instance methods 和 class methods。其原理如下:
- 任何 object 都是Object的子类实例,而 Object 本身继承自Kernel
- Kernel module 定义了 include 方法,其中会调用 self.included
- 这个 included 可以被用来修改包含 module 方法的类
- 定义 module 的时候,用一个 sub module 来定义所有的 class methods
- 在 module 中重写 included 方法,调用 extend 来扩展上述 sub module 中的 methods 为 class methods
例子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|