我正在使用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/

10-13 02:09
查看更多