Вопрос
Как получается, что Ruby неявно разрешает методы доступа класса вне класса?
Пример:
class Candy
def land
homer
end
end
def homer
puts "Hello"
end
Candy.new.land #Outputs Hello
Решение
Определение метода «гомер» заключается в добавлении метода в класс Object.Это не определение свободной функции.
Класс Candy неявно наследуется от Object и поэтому имеет доступ к методам Object.Когда вы вызываете «гомер» в методе «земля», разрешение метода не может найти определение в текущем классе, переходит к суперклассу, находит метод, который вы добавили в объект, и вызывает его.
Другие советы
Простой способ узнать, что происходит
Какие классы/модули ищутся для разрешения методов, используемых в объектах Candy?
p Candy.ancestors #=> [Candy, Object, Kernel]
Есть ли у Candy метод под названием Гомер?
p Candy.instance_methods(false).grep("гомер") #=> []
p Candy.private_instance_methods(false).grep("homer") #=> []
OK Candy не имеет метода под названием «гомер».
Что дальше в цепочке поиска (см. 1) => «Объект»
Есть ли у Object метод под названием «Гомер»?p Object.instance_methods(false).grep("гомер") #=> []
p Object.private_instance_methods(false).grep("гомер") #=> ["гомер"]
Candy имеет объект в своей цепочке поиска, который, в свою очередь, имеет частный метод экземпляра «homer», поэтому разрешение метода успешно.
А заявление о защите всегда определяет метод в классе чего угодно себя находится в точке определения
Что себя непосредственно перед определением Гомера?
p self #=> Main def Гомер ставит "Hello" End
Так каков его тип?
p self.class #=> Объект
Вот почему Гомер заканчивается Объект
Технически определение homer
метод на самом деле находится на Kernel
модуль, который смешивается с Object
, не на Object
напрямую.Так когда homer
не является локальной переменной или методом экземпляра, определенным в Candy
, цепочка наследования методов Ruby выполняется через Object
а затем в смешанный Kernel
модуль, а затем запускается этот код.
Редактировать: Извините, я не знаю, почему я так подумал.Похоже, метод действительно живет Object
.Не уверен, что на практике это имеет большое значение, но мне следовало убедиться в этом, прежде чем публиковать информацию.
В Ruby нет свободно плавающих функций.Каждый метод принадлежит некоторому объекту.Методы, которые вы def
на верхнем уровне фактически становятся методами экземпляра класса Object
.Потому что все является Object
на каком-то уровне все объекты имеют доступ к Object
методы экземпляра.