Ruby: как работает постоянный поиск в instance_eval / class_eval? - PullRequest
3 голосов
/ 10 июня 2010

Я пробираюсь через Pickaxe 1.9, и меня немного смущает постоянный поиск в блоках instance / class_eval. Я пользуюсь 1.9.2.

Кажется, что Ruby обрабатывает постоянный поиск в * _eval блоках так же, как и метод-поиск:

  1. ищите определение в receive.singleton_class (плюс mixins);
  2. затем в receive.singleton_class.superclass (плюс mixins);
  3. затем продолжайте движение вверх по собственной цепи, пока не доберетесь до #<Class:BasicObject>;
  4. суперклассом которого является Class;
  5. , а затем вверх по остальной цепочке предков (включая 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

Ответы [ 2 ]

1 голос
/ 16 декабря 2010

В 1.9.2 постоянный поиск снова изменился , что эквивалентно поведению 1.8.7.

class A
  class B
    class C
    end
  end
end

A.class_eval { B } # => NameError
A.instance_eval { B } # => NameError
A.new.instance_eval { B } # => A::B

По существу, константы имеют квазилексическую область видимости. Это ИСПОЛЬЗУЕТСЯ, чтобы отличаться между ветками 1.9.x и 1.8.x, и это сделало кросс-совместимость библиотек болью, поэтому они изменили ее обратно.

Призыв Иегуды Каца (успешный) восстановить поведение 1,8 *

0 голосов
/ 26 января 2016

Константы эффективно лексически ограничены, поэтому вы не можете получить к ним доступ за пределами иерархии модулей, в которой они определены.Есть хорошее объяснение здесь и немного не по теме, но хорошее прочтение здесь .

...