Я пробираюсь через Pickaxe 1.9, и меня немного смущает постоянный поиск в блоках instance / class_eval. Я пользуюсь 1.9.2.
Кажется, что Ruby обрабатывает постоянный поиск в * _eval блоках так же, как и метод-поиск:
- ищите определение в receive.singleton_class (плюс mixins);
- затем в receive.singleton_class.superclass (плюс mixins);
- затем продолжайте движение вверх по собственной цепи, пока не доберетесь до
#<Class:BasicObject>
;
- суперклассом которого является Class;
- , а затем вверх по остальной цепочке предков (включая
Object
, в котором хранятся все константы, которые вы определили на верхнем уровне), проверяя наличие миксинов по пути
Это правильно? Обсуждение Кирки немного кратко.
Некоторые примеры:
class Foo
CONST = 'Foo::CONST'
class << self
CONST = 'EigenFoo::CONST'
end
end
Foo.instance_eval { CONST } # => 'EigenFoo::CONST'
Foo.class_eval { CONST } # => 'EigenFoo::CONST', not 'Foo::CONST'!
Foo.new.instance_eval { CONST } # => 'Foo::CONST'
В примере class_eval Foo-the-class не является остановкой в цепочке предков Foo-the-object!
И пример с миксинами:
module M
CONST = "M::CONST"
end
module N
CONST = "N::CONST"
end
class A
include M
extend N
end
A.instance_eval { CONST } # => "N::CONST", because N is mixed into A's eigenclass
A.class_eval { CONST } # => "N::CONST", ditto
A.new.instance_eval { CONST } # => "M::CONST", because A.new.class, A, mixes in M