常量查找的顺序依次如下:

#其中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

results matching ""

    No results matching ""