Is there a way to know what are the subclasses of a given class?


#1

Hello

Do you know if there’s a trick to retrieve a list of all the subclasses
of a
given class ?

class A
class B
end
class C
end
end

like A.subclasses --> [B,C] ?

Thanks
Sandro


#2

[SOLVED]

I just find out that you can call:

A.constants --> [“B”,“C”]

Thank you

Sandro

On Wed, Nov 19, 2008 at 10:10 AM, Sandro P. <


#3

In your above example, B is not subclass of A (B is not even defined,
just A::B).

Also, how about

class A
class B
end
class C
end
D = E = F = 5
end

A.constants
=> [“C”, “B”, “D”, “F”, “E”]

What are you trying to do exactly? Maybe modules would be better?

Cheers,
Peter


http://www.rubyrailways.com
http://scrubyt.org


#4

Sandro P. wrote:

Do you know if there’s a trick to retrieve a list of all the subclasses
of a
given class ?

Only this that I know of:

class A; end
class B<A; end

require ‘enumerator’
p ObjectSpace.to_enum(:each_object, Class).
select { |c| c.superclass == A }


#5

Sandro

class A
class B
end
class C
end
end

like A.subclasses --> [B,C] ?

As has been mentioned, in your example B and C are not subclasses of A.
If you want to list all subclasses of a class you can do this:

irb(main):001:0> class A
irb(main):002:1> class << self
irb(main):003:2> attr_accessor :subclasses
irb(main):004:2> end
irb(main):005:1> def self.inherited child
irb(main):006:2> (A.subclasses ||= []) << child
irb(main):007:2> end
irb(main):008:1> end
=> nil
irb(main):009:0> A.subclasses
=> nil
irb(main):010:0> class B < A; end;
irb(main):011:0* A.subclasses
=> [B]
irb(main):012:0> class C < B; end;
irb(main):013:0* A.subclasses
=> [B, C]
irb(main):014:0> class D < A; end;
irb(main):015:0* A.subclasses
=> [B, C, D]

Hope this helps,

Jesus.


#6

Thanks Peter :smiley:

That exactly what I was lloking for :slight_smile:


#7

On Wed, Nov 19, 2008 at 11:36 AM, Michael F.
removed_email_address@domain.invalid wrote:

On Wed, Nov 19, 2008 at 7:12 PM, Jesús Gabriel y Galán
removed_email_address@domain.invalid wrote:

Little different style maybe:

class A
@subclasses = []
def self.inherited(into) @subclasses << into end
def self.subclasses() @subclasses end
end

Yep, much cleaner :-).
I made a mess while I was typing in irb about closing the << self early,
and forgetting to initialize the array, so that was the result. I
probably wanted to type this:

irb(main):001:0> class A
irb(main):002:1> class << self
irb(main):003:2> attr_reader :subclasses
irb(main):004:2> def inherited(child)
irb(main):005:3> subclasses << child
irb(main):006:3> end
irb(main):007:2> end
irb(main):008:1> @subclasses = []
irb(main):009:1> end

but anyway your version is cleaner…

Jesus.


#8

On Wed, Nov 19, 2008 at 7:12 PM, Jesús Gabriel y Galán
removed_email_address@domain.invalid wrote:

Sandro

class A

=> nil
Hope this helps,

Jesus.

Little different style maybe:

class A
@subclasses = []
def self.inherited(into) @subclasses << into end
def self.subclasses() @subclasses end
end

nil

class B < A
end

nil

A.subclasses

[B]

And a slower and hacky alternative:

require ‘set’; found = Set.new; ObjectSpace.each_object(Class){|o|
found << o if o < A }

446

found

#<Set: {B}>

^ manveru