Reputation: 2998
Note that my question is different from this question because I'm asking for all descendants (including descendants of descendants) of a class.
Moreover, I would prefer to use something like
class Animal
def self.inherited(subclass)
@descendants = []
@descendants << subclass
end
def self.descendants
puts @descendants
end
end
because it's way faster than getting all classes and filtering for descendants.
Upvotes: 0
Views: 1047
Reputation: 110665
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]
Alternatively, you can use ObjectSpace#each_object to obtain A
's descendants.
ObjectSpace.each_object(Class).select { |c| c < A }
#=> [F, E, D, C, B]
If you wish to obtain the ordering of
arr = [B, C, D, E, F]
you could write
(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]}
Upvotes: 1