私は Pickaxe 1.9 を使って作業を進めていますが、instance/class_eval ブロックの定数ルックアップに少し混乱しています。私は1.9.2を使用しています。
Ruby は *_eval ブロック内の定数ルックアップをメソッド ルックアップと同じ方法で処理しているようです。
- receiver.singleton_class (および mixins) で定義を探します。
- 次に、receiver.singleton_class.superclass (および mixins) で。
- 次に、 に到達するまで固有連鎖を続けます
#<Class:BasicObject>
。 - そのスーパークラスは Class です。
- そして、残りの先祖チェーン (
Object
トップレベルで定義したすべての定数を格納する を含む) を上に移動し、途中で mixin をチェックします。
これは正しいです?つるはしの議論は少し簡潔です。
いくつかの例:
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