2012-01-01 7 views
5

Вдохновленный этим article, я играл с методом Ruby, вызывая иерархию и замечая что-то странное.Иерархия вызова метода Ruby

Дано:

class B 
    def foo 
    "- Instance method defined by B" 
    end 

    def method_missing(method) 
    puts "- method_missing (#{method}) on b. Redirecting to b.foo\n" 
    foo 
    end 
end 

b = B.new 

def b.foo 
    "- Method defined directly on an instance of B\n" + super 
end 

def b.method_missing(method) 
    "- method_missing (#{method}) on b. Calling super\n" + super 
end 

puts "Calling 'bar' on b of type #{b.class}:" 
puts b.bar 

Бег дает:

Calling 'bar' on b of type B: 
- method_missing (bar) on b. Redeirecting to b.foo 
- method_missing (bar) on b. Calling super 
- Method defined directly on an instance of B 
- instance method defined by B 

Мой вопрос:

Поскольку я звоню b.bar (на объекте), как же экземпляр этого класса, метод вызывается до вызова метода экземпляра объекта objet?

я ожидал бы b.method_missing(method) называться первым, то экземпляр этого класса method_missing(method) (так я называю супер? Но супер классно иерархия ...), который делает редирект от bar к foo. Кроме того, как получилось, после перенаправления на foo вызывается метод missing_method экземпляра? Нам просто сказали, что мы перенаправлены ...

Я думаю, что я не понимаю понятия о том, как Ruby позволяет определить метод экземпляра для экземпляра класса (нового для меня), в отличие от определяя его как метод экземпляра класса (классические языки).

Я надеюсь, что этот вопрос имеет смысл, может быть, моя голова все еще вращается с прошлой ночи ...

+1

I удаленный ненужный код, чтобы сделать проблему более очевидной. Как правило, рекомендуется создать * минимальный * пример проблемы. –

ответ

4

Проблема заключается в том, что ваш вывод не отражает фактический порядок исполнения. Давайте посмотрим на выходе:

method_missing (bar) on b. Redeirecting to b.foo 
method_missing (bar) on b. Calling super 

На первый взгляд, это создает впечатление, что B#method_missing вызывается перед одноэлементной методом b.method_missing который поднимает два вопроса, которые Вы описываете. На самом деле, хотя, b.method_missing правильно называется первым. Это становится ясно, если посмотреть на то, как оператор puts b.bar оценивается:

  1. b не имеет какого-либо метода bar, так b.method_missing называется строкой 'bar' в качестве аргумента.
  2. b.method_missing в свою очередь вызывает метод B#method_missing с использованием ключевого слова super.
  3. B#method_missing использует puts для вывода первой строки видны выше
  4. одноточечного метода b.foo называется
  5. внешнего puts выполняется, который выводит строку в b.method_missing вместе с возвращаемым значением b.foo
+2

+1; Избили меня. –

+0

Niklas, спасибо за разъяснение (и удаление ненужного кода). Спасибо за ваш ответ! – dynex

+0

Запуск его в отладчике, конечно, разъясняет его. Я должен был сделать это с самого начала - извините, ребята, и спасибо за ваше терпение. – dynex

Смежные вопросы