Ruby元编程读书笔记十五
Eigenclass Practice
前面我们说过 attr_accessor() 方法,它能为任何 对象 创建属性:
class MyClass
attr_accessor :a
end
obj = MyClass.new
obj.a = 2
obj.a #=> 2
但是,如果想给类创建属性呢?你可能会试图重新打开 Class 并且在那里定义属性:
class MyClass;end
class Class
attr_accessor :b
end
MyClass.b = 42
MyClass.b #=> 42
但这样做会给所有的类都添加这个属性。如果希望添加专属于 MyClass 的属性,就需要使用另一种技术—-在它的 eigenclass 中定义该属性:
class MyClass
class << self
attr_accessor :c
end
end
MyClass.c = 'It works!'
MyClass.c #=> "It works!"
一个属性实际上只是一对方法,如果在 eigenclass 中定义这些方法,则它们实际上会成为类方法。
当类包含模块时,能够扩展该类的实例方法。如果想扩展该类的类方法,则应该在它的 eigenclass 中包含模块:
module MyModule
def my_method; 'hello'; end
end
class MyClass
class << self
include MyModule
end
end
MyClass.my_method #=> "hello"
my_method() 方法是 MyClass 的 eigenclass 的一个实例方法,这样,my_method() 也是 MyClass 的一个类方法。这种技术称为 类扩展。
类方法其实是单件方法的特例,因此可以把这种技巧推广到任意对象。一般情况下,这种技术称为 对象扩展:
module MyModule
def my_method; 'hello'; end
end
obj = Object.new
class << obj
include MyModule
end
obj.my_method #=> "hello"
obj.singleton_methods #=> [:my_method]
类扩展 和 对象扩展 的应用非常普遍,因此 Ruby 为它们专门提供了一个叫做 Object#extend() 的方法:
module MyModule
def my_method; 'hello'; end
end
obj = Object.new
obj.extend MyModule
obj.my_method #=> "hello"
class MyClass
extend MyModule
end
MyClass.my_method #=> "hello"