в Ruby вы можете открыть существующие классы и добавить методы. То есть можно сказать:
class Foo
def bob
return "hello from bob"
end
end
эти методы хранятся где-то во внутреннем словаре (возможно, переменной экземпляра) Foo
-класса (который является просто экземпляром Class
-класса и, следовательно, имеет переменных экземпляра)
Но удивительно то, что вы также можете добавлять методы к экземплярам существующих объектов
foo = Foo.new
foo2 = Foo.new
def foo.fred
return "I am fred"
end
foo.fred #=> "I am fred"
foo2.fred #=> NoMethodError
но Где этот метод на самом деле хранится ?
Оказывается, Ruby создает за кулисами новый класс (иногда называемый синглтон-класс , метакласс или eigenclass ), который вставляется в наследственную иерархию между классом Foo
и его экземпляром.
Итак, отношения наследования выглядят так:
foo < (eigenclass of foo) < Foo < Class
(если вы скажете foo.superclass, вы не увидите одноэлементный класс)
синтаксис class << X
- это способ получить доступ к этому специальному классу, чтобы вы могли напрямую им манипулировать. Следующие блоки кода в точности эквивалентны:
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
, что делает его методом класса для Foo
все это более четко объяснено в главе о классах кирки (к сожалению, в веб-версии отсутствуют диаграммы) и _whys Четкое представление метаклассов