Ruby:常量查找如何在instance_eval/class_eval中工作? [英] Ruby: how does constant-lookup work in instance_eval/class_eval?

查看:129
本文介绍了Ruby:常量查找如何在instance_eval/class_eval中工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过Pickaxe 1.9进行工作,并且对instance/class_eval块中的常量查找感到有些困惑.我正在使用1.9.2.

I'm working my way through Pickaxe 1.9, and I'm a bit confused by constant-lookup in instance/class_eval blocks. I'm using 1.9.2.

似乎Ruby在* _eval块中处理常量查找的方式与方法查找相同:

It seems that Ruby handles constant-lookup in *_eval blocks the same way it does method-lookup:

  1. 在receiver.singleton_class(加上mixins)中查找定义;
  2. 然后进入receive.singleton_class.superclass(加上mixins);
  3. 然后继续沿着特征链前进,直到到达#<Class:BasicObject>
  4. 其超类为Class;
  5. ,然后在祖先链的其余部分(包括Object,它存储您在顶级定义的所有常量),沿途检查是否有混合.
  1. look for a definition in receiver.singleton_class (plus mixins);
  2. then in receiver.singleton_class.superclass (plus mixins);
  3. then continue up the eigenchain until you get to #<Class:BasicObject>;
  4. whose superclass is Class;
  5. and then up the rest of the ancestor chain (including Object, which stores all the constants you define at the top-level), checking for mixins along the way

这是正确的吗?镐的讨论有点简短.

Is this correct? The Pickaxe discussion is a bit terse.

一些例子:

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的祖先链上的停靠点!

In the class_eval example, Foo-the-class isn't a stop along Foo-the-object's ancestor chain!

还有一个mixin示例:

And an example with mixins:

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行为.

In 1.9.2 the constant lookup has changed again to be equivalent to the 1.8.7 behavior.

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分支之间有所不同,这使库的跨兼容性变得很痛苦,因此他们将其改回了.

Basically, the constants are quasi-lexically scoped. This USED to be different between 1.9.x and 1.8.x branches, and it made library cross compatibility a pain, so they changed it back.

Yehuda Katz(成功)呼吁恢复1.8行为

这篇关于Ruby:常量查找如何在instance_eval/class_eval中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆