在 Ruby 中,您可以重新打开现有的类并添加方法。也就是说,你可以说:
class Foo
def bob
return "hello from bob"
end
end
这些方法存储在Foo-class 的内部字典(可能是实例变量)的某个位置(它只是Class-class 的一个实例,因此有 个实例变量)
但令人惊讶的是,您还可以向现有对象的实例添加方法
foo = Foo.new
foo2 = Foo.new
def foo.fred
return "I am fred"
end
foo.fred #=> "I am fred"
foo2.fred #=> NoMethodError
但是这个方法实际存储在哪里?
原来 Ruby 在后台创建了一个新类(有时称为 singleton class、metaclass 或 eigenclass),它被插入到继承中Foo-class 及其实例之间的层次结构。
所以继承关系是这样的:
foo < (eigenclass of foo) < Foo < Class
(如果你说 foo.superclass 你不会看到单例类)
class << X-syntax 是一种进入这个特殊类的方法,这样你就可以直接操作它。以下代码块完全相同:
def foo.bar
return "xy"
end
# is exactly the same as
class << foo
def bar
return "xy"
end
end
所以class Foo < Bar 和class << Foo 之间的相似性并非偶然,两者都存在继承。
将class << X 视为“打开X 的元类”
在 Ruby 中要记住的是,类本身就是对象。 (Class 类的实例)所以如果你说:
class Foo
class << self
def k
return "x"
end
end
end
(self 在此代码块中绑定到Foo)所以k 是Foo 的特征类的实例方法,这使它成为@987654340 的类方法@
所有这一切在chapter about classes of the Pickaxe(不幸的是网络版不包含图表)和_whys Seeing Metaclasses Clearly中都有更清楚的解释