当您定义常量时,您并不是将常量分配给self。您正在当前模块嵌套中定义一个常量。
当您显式打开一个类或模块时,您还设置了模块嵌套:
module Foo
BAR = 1
puts Module.nesting.inspect # [Foo]
end
当你这样做时User.class_eval { AVOCADO = 'fruit' }
模块嵌套是“Main”,也称为全局对象:
User.class_eval do
ADVOCADO = 'Fruit'
puts Module.nesting.inspect # []
end
块实际上并不改变模块嵌套。const_set
另一方面,在另一个模块嵌套中定义一个常量。
Ruby 实际上并没有两次定义该常量。相反,当您使用 const_get 或引用常量而不显式使用范围解析运算符时,Ruby 将查看模块嵌套并将树向上遍历到全局范围:
class A
end
B = 'eureka'
A.const_get(:B) # 'eureka'
这就是您如何引用顶级常量而无需在它们前面加上::
。但是当你使用User::ADVOCADO
你明确引用了里面的常量User
.
当谈到这个令人担忧的例子时,你误解了正在发生的事情。根本不是关于class_eval
。您正在定义常数FruitConcern::AVOCADO
.
当你然后包括FruitConcern
into User
你正在添加FruitConcern
到包含在常量查找中的祖先链上:
module FruitConcern
ADVOCADO = 'fruit'
end
class User
include FruitConcern
end
User::ADVOCADO # fruit
See:
- Ruby 模块:包含、前置、扩展 https://medium.com/@leo_hetsch/ruby-modules-include-vs-prepend-vs-extend-f09837a5b073
- 关于 Ruby 中的常量查找,您想了解的所有信息 https://cirw.in/blog/constant-lookup.html