为特定的 class 创建一个 superclasses 数组

Creating an array of superclasses for a particular class

我正在尝试为给定的 class 创建一个包含所有超级 class 的数组。我试图通过使用循环来解决这个问题。为什么这不起作用?

class Object
  def superclasses
    array = []
    klass = self.superclass
    unless klass == nil
      array << klass
      klass = klass.superclass
    end
    array
  end
end

class Bar
end

class Foo < Bar
end

p Foo.superclasses  # should be [Bar, Object, BasicObject]

unless 不是循环。您正在寻找的是 until:

class Object
  def superclasses
    array = []
    klass = self.superclass
    until klass == nil
      array << klass
      klass = klass.superclass
    end
    array
  end
end

class Bar
end

class Foo < Bar
end

p Foo.superclasses # Prints "[Bar, Object, BasicObject]"

此外,您不需要为此使用新方法。已经有一个名为 Module#ancestors 的方法,它基本上可以满足您的需求:

class Bar
end

class Foo < Bar
end

p Foo.ancestors # Prints "[Foo, Bar, Object, Kernel, BasicObject]"

请注意,ancestors 的 return 值包括 Foo 本身,以及已包含在继承链中的模块,如 Kernel。如果你不想这样,你可以这样定义 superclasses

class Module
  def superclasses
    ancestors[1..-1].select{|mod| mod.is_a? Class }
  end
end

class Bar
end

class Foo < Bar
end

p Foo.superclasses # Prints "[Bar, Object, BasicObject]"

您需要一个循环来继续查找超类:

def superclasses
  array = []
  klass = self.superclass
  while klass
    array << klass
    klass = klass.superclass
  end
  array
end

我认为使用递归看起来更好一些

def superclasses
  return [] if superclass.nil?
  [superclass].concat superclass.superclasses
end

实际上这个方法应该在 Class 中定义,因为不是每个 Object 都响应 superclass

Ruby 的内置方式是 Module#ancestors。但它并不完全相同,因为这也考虑了包含的模块。然而,内置方法是执行此操作的正确方法,因为严格的超类链并不能真正为您提供 Ruby.

中的全貌

获取超类的另一种方法

class Object
  def superclasses
    ObjectSpace.each_object(Class).select { |klass| klass < self }
  end
end