Метод доступа в Ruby - PullRequest
       18

Метод доступа в Ruby

9 голосов
/ 01 октября 2008

Как получается, что Ruby неявно разрешает доступ к методам класса за пределами класса?

Пример:

class Candy
    def land
        homer
    end
end

def homer
    puts "Hello"
end

Candy.new.land #Outputs Hello

Ответы [ 4 ]

24 голосов
/ 01 октября 2008

Определение метода "homer" - добавление метода к классу Object. Это не определение свободной функции.

Класс Candy неявно наследуется от Object, и поэтому имеет доступ к методам в Object. Когда вы вызываете «homer» в методе «land», разрешение метода не может найти определение в текущем классе, переходит к суперклассу, находит метод, добавленный в Object, и вызывает его.

5 голосов
/ 03 октября 2008

Простой способ узнать, что происходит

  1. Какие классы / модули ищутся для разрешения методов, используемых в объектах Candy?

    p Candy.ancestors # => [Candy, Object, Kernel]

  2. Есть ли у Кенди метод с именем homer?

    p Candy.instance_methods (false) .grep ("homer") # => []

    p Candy.private_instance_methods (false) .grep ("homer") # => []

  3. ОК У Кенди нет метода, называемого «Гомер».

  4. Что дальше в цепочке поиска (см. 1) => «Объект»

  5. Есть ли в Object метод с именем "homer"? p Object.instance_methods (false) .grep ("homer") # => []

    p Object.private_instance_methods (false) .grep ("homer") # => ["homer"]

Candy имеет Object в своей цепочке поиска, которая, в свою очередь, имеет частный экземплярный метод "homer", поэтому разрешение метода успешно выполняется

Оператор def всегда определяет метод в классе независимо от того, self находится в точке определения

  1. Что такое self непосредственно перед определением Гомера?

    p self # => main Def Homer ставит "Привет" конец

  2. Так каков его тип?

    p self.class # => Объект

Именно поэтому Гомер заканчивается Объектом

4 голосов
/ 02 октября 2008

Технически, определение метода homer фактически на модуле Kernel, который смешивается с Object, а не с Object напрямую. Поэтому, когда homer не является локальной переменной или методом экземпляра, определенным в Candy, цепочка наследования метода Ruby отслеживается через Object, а затем в смешанный модуль Kernel, а затем выполняется этот код.

Редактировать: Извините, я не знаю, почему я так подумал. Похоже, что метод действительно живет на Object. Не уверен, что это имеет большое значение на практике, но я должен был подтвердить вещи перед публикацией.

0 голосов
/ 27 ноября 2011

Ruby не имеет свободно плавающих функций. Каждый метод принадлежит некоторому объекту. Методы, которые вы def на верхнем уровне, фактически становитесь методами экземпляра класса Object. Поскольку на каком-то уровне все является Object, все объекты имеют доступ к методам экземпляров Object.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...