我正在使用pickaxe 1.9,我对实例/类评估块中的常量查找有点困惑。我用的是1.9.2。
似乎Ruby在评估块中处理常量查找的方式与处理方法查找的方式相同:
在receiver.singleton_类(加上mixins)中查找定义;
然后在receiver.singleton_class.superclass中(加上mixins);
然后继续向上移动特征链,直到到达#<Class:BasicObject>
;
其超类是类;
然后在祖先链的其余部分(包括存储您在顶层定义的所有常量的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'
在类求值示例中,foo类不是对象的祖先链上的一个停止符!
还有一个混音的例子:
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
最佳答案
在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分支之间曾经是不同的,它使库的交叉兼容性成为一种痛苦,所以他们改变了它。
Yehuda Katz's (successful) appeal to restore 1.8 behavior
关于ruby - Ruby:常量查找如何在instance_eval/class_eval中工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3015947/