如何使用`self.inherited`获取Ruby中所有类的后代?

时间:2017-04-03 14:48:30

标签: ruby

请注意,我的问题与this question不同,因为我要求所有后代(包括后代的后代)。

此外,我更喜欢使用像

这样的东西
class Animal   
  def self.inherited(subclass)
    @descendants = []
    @descendants << subclass   
  end

  def self.descendants
    puts @descendants    
  end
end

因为它比获取所有类和过滤后代更快。

1 个答案:

答案 0 :(得分:1)

class A
  singleton_class.send(:attr_reader, :descendants)
  @descendants = []
  def self.inherited(subclass)
    A.descendants << subclass
  end
end

A.methods(false)
  #=> [:inherited, :descendants, :descendants=]

class B < A; end
class C < B; end
class D < B; end
class E < C; end
class F < E; end

A.descendants
  #=> [B, C, D, E, F]

或者,您可以使用ObjectSpace#each_object获取A的后代。

ObjectSpace.each_object(Class).select { |c| c < A }
  #=> [F, E, D, C, B]

如果您想获得

的订购
arr = [B, C, D, E, F]
你可以写

(arr << A).each_with_object({}) { |c,h| h[c] =
  arr.each_with_object([]) { |cc,a| a << cc if cc.superclass == c } }
  #=> {B=>[C, D], C=>[E], D=>[], E=>[F], F=>[], A=>[B]}