常量查找的顺序依次如下:
#其中Module.nesting和Class.nesting功能一致,如果level1中如果找不到,依次找level2和level3
level1:Module.nesting
level2:Module.nesting.first.ancestors
level3:Object中
Object中常量的处理
没有namespace的常量定义被认为是定义在Object类中,比如下面的几种常量定义方式被认为是相同的
Array == Object::Array #true
Array == ::Array #true,使用::来获取顶级常量
在namespace中使用核心类名称的类,不会使用真正的核心类,而认为是使用区别于核心类的带有namespace的新的类
module Cluster
class Array
def initialize(n)
#这里的Array是从上面的常量的查找顺序,是使用Cluster::Array
@array = Array.new
#如果要使用核心的Array类
@array = Object::Array.new
@array = ::Array.new
end
end
end
ruby中默认的类都是继承自Object,因此可以使用核心类,也就是定义的顶级常量,但是如果是继承自BasicObject类,那么将不能直接使用顶级常量,必须使用::符号
#error
class Foo < BasicObject
Kernel
end
# NameError: uninitialized constant Foo::Kernel
#success
class Foo < BasicObject
::Kernel
end
Module.nesting的使用
module A
module B; end
module C
module D
p Mouduel.nesting #[A::C::D, A::C, A]
B == A::B #true
B == Object::A::B #true
end
end
end
从上面的代码中,常量B依次从Module.nesting中查找,最后从module A中获得常量B,因此
#和上面的代码效果一致
B == A::B #true
Array == Object::Array #true
注意的问题:在没有预先定义命名空间的情况使用namespace::class会报错
#预先没有定义,会出现nameerror
class One::Demo
end
#解决方案,先定义一个module
module One
end
class One::Demo
end
不同的nesting形式
#代码示例1
module A
module B
Module.nesting == [A::B, A]
end
end
#代码示例2
module A::B
Module.nesting == [A::B]
end
读取nesting为空数组的情况
#匿名类
class A
end
B = Class.new(A) do
def self.hi
p Class.nesting
end
end
B.hi #[]
#使用block中
class C < A
puts Class.nesting.join(', ') #
def self.hi
yield
end
end
C.hi { p Class.nesting } #[]
在单例类中的nesting情况
class D
class << self
p Class.nesting #[#<Class:D>, D]
end
end
Module.nesting.first.ancestors:就是从当前打开的最里面的class或者module
#一般方式
class A
module B; end
end
class C < A
#类C中并没有查找到B常量的定义,于是module.nesting没有,从module.nesting.first.ancestors中就是A中查找
B == A::B #true
end
误区:从self.class中开始查找,其实有误,而是从打开类中开始查找
class A
def get_c; C; end
end
class B < A
module C; end
end
B.new.get_c #self.class是B,但是并不会查找B::C 当前打开类是A
# NameError: uninitialized constant A::C