在 Ruby 中,您可以重新打开现有的类并添加方法。也就是说,你可以说:
class Foo
def bob
return "hello from bob"
end
end
这些方法存储在 -class 的内部字典(可能是实例变量)的某个位置Foo
(这只是 -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 在幕后创建了一个新类(有时称为单例类、元类或特征类),它被插入到-class 及其实例之间的继承层次结构中。Foo
所以继承关系是这样的:
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
中绑定到)也是的 eigenclass 的实例方法,这使其成为 的类方法Foo
k
Foo
Foo
所有这一切都在关于 Pickaxe 类的章节中更清楚地解释(不幸的是,Web 版本不包含图表)和 _whys Seeing Metaclasses Clearly