В Ruby есть какие-либо связанные применения синтаксиса:класс << сам … конец
Вопрос
class << self
attr_accessor :n, :totalX, :totalY
end
Приведенный выше синтаксис используется для определения переменных экземпляра класса.Но когда я думаю о том, что подразумевает синтаксис, для меня это не имеет никакого смысла, поэтому мне интересно, используется ли этот тип синтаксиса для каких-либо других типов определений.Моя путаница вот в чем:
class << self
Оператор добавления обычно означает «добавление того, что справа, к объекту слева».Но в контексте этого блока, как это означает «поместить содержимое этого блока в определение экземпляра класса, а не в экземпляр»?
По той же причине я не понимаю, почему в одном контексте class << self может определять переменные экземпляра класса, а в другом он, похоже, создает переменные класса, такие как здесь:
class Point
# Instance methods go here
class << self
# Class methods go here
end
end
Решение
в Ruby вы можете повторно открыть существующие классы и добавить методы.То есть, вы можете сказать:
class Foo
def bob
return "hello from bob"
end
end
эти методы сохраняются где-то во внутреннем словаре (возможно, в переменной экземпляра) 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 за кулисами создает новый класс (иногда называемый одноэлементный класс, метакласс или собственный класс), который вставляется в иерархию наследования между тот Foo
-класс и его экземпляр.
Таким образом, отношения наследования выглядят следующим образом:
foo < (eigenclass of foo) < Foo < Class
(если вы скажете foo.superclass, вы не увидите класс Singleton)
тот 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
, что делает его методом класса для Foo
все это более понятно объяснено в глава о классах Кирки (веб-версия, к сожалению, не содержит схем) и _whys Ясно видеть метаклассы
Другие советы
Представьте, что класс содержит словарь членов, включая все методы доступа и переменные экземпляра.Когда вы говорите классу «добавить» к «самому себе», вы говорите «добавьте их в словарь членов класса».
Хотя я признаю, что обозначения немного странные.
на самом деле сложно думать об этом как об операторе добавления.лучший способ взглянуть на это так же, как class Foo
открывает класс Foo, то есть устанавливает «self» для объекта класса Foo, создавая его при необходимости, поэтому class << self
открывает собственный класс текущего объекта self.обратите внимание, что это не ограничивается self - для любой панели объекта вы можете сказать class << bar, чтобы открыть собственный класс этого объекта.
class A
def hello
print "hello world"
end
end
a = A.new
b = A.new
class << a
def goodbye
print "goodbye cruel world"
end
end
a.hello
b.hello
a.goodbye
b.goodbye