• #10 楼 @iBachue 说明这是个值得关注的经典问题嘛!呵呵

  • matz 的设计就是要隐藏单键类,这是一种设计原则。但对于要了解元编程的人来说,又必须要透彻了解隐藏类的全部体系关系。我写了一段测试代码(https://github.com/homeway/fulll_ancestors/blob/master/ancestors.rb

    
    #encoding: utf-8
    class Object
      def full_ancestors
        instance_ancestors << "\n" << eigein_ancestors
      end
      def instance_ancestors
        return "我只是一个对象,不能派生实例,也就没有实例的祖先链。" unless respond_to? :ancestors
        return "作为类,若派生实例将产生的祖先链是:[#{ancestors.join(',')}]"
      end
      def eigein_ancestors
        eigeinclass = class << self;self;end
        ancestors = [eigeinclass]
        modules = eigeinclass.included_modules
        x = eigeinclass
        while x.superclass do
          x = x.superclass
          ancestors << x
          deleted = []
          modules.each do |m|
            if x.include? m
              unless x.superclass and x.superclass.include? m
                ancestors << m
                deleted << m
              end
            end
          end
          deleted.each do |m|
            modules.delete m
          end
        end
        "作为对象,我的实际祖先链是:[#{ancestors.join(',')}]"
      end
    end
    
    module M; end
    class A; end
    class B < A; end
    A.extend M
    
    puts ''
    puts A.full_ancestors
    puts B.full_ancestors
    
    

    那么输出结果大致如下:

    作为类,若派生实例将产生的祖先链是:
    [A,Object,Kernel,BasicObject]
    
    作为对象,我的实际祖先链是:
    [#<Class:A>,#<Class:Object>,#<Class:BasicObject>,Class,Module,Object,Kernel,BasicObject]
    
    作为类,若派生实例将产生的祖先链是:
    [B,A,Object,Kernel,BasicObject]
    
    作为对象,我的实际祖先链是:
    [#<Class:B>,#<Class:A>,M,#<Class:Object>,#<Class:BasicObject>,Class,Module,Object,Kernel,BasicObject]
    
    

    Matz 的实现只是过滤掉了#部分的隐藏类,而实际上对象和类在查找方法时,仍将按照上面所输出的实际祖先链顺序来查找。