Ответ 1
в 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 создает новый класс за кулисами (иногда называемый singleton class, metaclass или eigenclass), который вставлен в наследственную иерархию между классом 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
привязан к Foo
в этом кодовом блоке), поэтому k
является методом экземпляра eigenclass Foo
, что делает его методом класса для Foo
все это объясняется более четко в главе о классах Pickaxe (к сожалению, веб-версия не содержит диаграмм) и _whys Видя метаклассы ясно