Неявный контекст и собственные классы
Недавно я нашел интересную статью о неявных контекстах в Ruby, и мне показалось, что этот опыт довольно открывающий. Я понял, что в Ruby есть ссылка не только на self
(получатель метода по умолчанию), но также к текущему классу (также известному как defaulte define или `klass'
).
Из статьи следует правильно предположить, что class
определение устанавливает оба self
и текущий класс для класса, который определяется; насколько мы рассматриваем нормальное определение метода (то есть, не используя точечный синтаксис для определения одноэлементных методов), в контексте определения метода с def
, self
ссылается на принимающий объект, а текущий класс не изменяется.
Причина, по которой я считаю безопасным не учитывать точечный синтаксис для определения, заключается в том, что Ruby также предлагает явный способ открытия собственного класса класса, и меня интересует понимание того, как управляются эти два неявных контекста при открытии собственного класса,
С помощью def
с хорошо известным синтаксисом для открытия собственного класса:
class << A
p self
def foo
# ...
end
end
определяет foo как одноэлементный метод A
т.е. метод экземпляра своего собственного класса (будь то A'
). Этот код также печатает #<Class:A>
поэтому правильно сказать, что <<
синтаксис устанавливает оба self
и текущий класс A'
?
2 ответа
Да, это фактически открывает блок под контролем A'. Также вы можете сказать, что он работает как class_eval из A'.
На самом деле, то, что вы написали, точно так же, как писать:
class A
class << self
def foo
#...
end
end
end
синтаксис класса << self указывает, что блок определений будет следовать, и это будет идти прямо к собственному классу объекта, переданного <<. И да, я сказал Объект, а не Класс. Попробуйте это (при условии определения класса выше):
a = A.new
class << a
def foo2
end
end
a.singleton_methods
b = A.new
b.singleton_methods
это означает, что в этом случае вы определяете метод foo2 в собственном классе объекта a. Но это собственный класс самого объекта, а не класса. Таким образом, другие объекты того же класса не будут использовать это определение foo2.
Так что это значит? Ruby является (или претендует на звание) чистым ОО-языком. Все является объектом. Объект определенного вами класса является объектом. Определенный вами класс также является объектом. Типа Класс. Который наследует от объекта. В Ruby все объекты имеют собственный класс. На самом деле, определение "методов класса" - это просто интерпретация его концепции. "Методы класса" на самом деле не методы класса, а методы, определенные в собственном классе класса. Итак, когда вы вызываете "метод класса", вы действительно вызываете объектный метод. Этот объект просто является классом, который вы определили. Как вы определяете методы собственного класса? Именно класс << сам синтаксис. "Я" в этом контексте - это то, что вы передали в качестве аргумента классу <<.