为特定类创建超类数组

时间:2015-01-23 16:23:12

标签: ruby loops superclass

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

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]

3 个答案:

答案 0 :(得分:3)

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的返回值包括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]"

答案 1 :(得分:3)

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

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中的全貌。

答案 2 :(得分:0)

获得超类的另一种方法

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