Find all subclasses of a class/module

Hi list,

I'm trying to find all the classes/modules that descend from a particular
class/module. Please tell me there's a better way than this:

···

--
James Coglan

the following are code in 6560’s gists · GitHub

class Module
  def subclasses
    classes =
    ObjectSpace.each_object do |klass|
      next unless Module === klass
      classes << klass if self > klass
    end
    classes
  end
end

I think the above code is good! but considering the class and module are
referenced by constants in ruby, use Module.constants is more naturally!
the following are mine!

the key is to get rid of the real constant such as PI and so on.

def find_children p_klass
  Module.constants.find_all{|c_klass| c_klass!=c_klass.upcase ? p_klass

(Object.const_get c_klass) : nil}

end

# test!

class MyString < String
end

puts find_children( String) #=> MyString

require 'benchmark'
include Benchmark

puts find_children(Benchmark).include?(Tms) #=> fase
puts Tms.name #=> Benchmark::Tms
puts find_children(Benchmark).include?("Tms") #=> true

···

--
Posted via http://www.ruby-forum.com/\.

just let ruby track it for you:

cfp:~ > cat a.rb
class A
end

class B < A
end

class C < A
end

class D < B
end

p D => D.subclasses
p C => C.subclasses
p B => B.subclasses
p A => A.subclasses
p Object => Object.subclasses

BEGIN {
   class Class
     def inherited other
       super if defined? super
     ensure
       ( @subclasses ||= ).push(other).uniq!
     end

     def subclasses
       @subclasses ||=
       @subclasses.inject( ) do |list, subclass|
         list.push(subclass, *subclass.subclasses)
       end
     end
   end
}

cfp:~ > ruby a.rb
{D=>}
{C=>}
{B=>[D]}
{A=>[B, D, C]}
{Object=>[A, B, D, C]}

a @ http://codeforpeople.com/

···

On Aug 21, 2008, at 7:55 AM, James Coglan wrote:

Hi list,

I'm trying to find all the classes/modules that descend from a particular
class/module. Please tell me there's a better way than this:

6560’s gists · GitHub

--
James Coglan

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

BEGIN {
class Class
   def inherited other
     super if defined? super
   ensure
     ( @subclasses ||= ).push(other).uniq!
   end

   def subclasses
     @subclasses ||=
     @subclasses.inject( ) do |list, subclass|
       list.push(subclass, *subclass.subclasses)
     end
   end
end
}

That's probably more efficient than my version, but won't it fail to capture
relationships of any pre-existing classes? Seems it will only affect classes
defined after it has been loaded.

that's correct. generally that's what people are after.

a @ http://codeforpeople.com/

···

On Aug 21, 2008, at 10:27 AM, James Coglan wrote:

That's probably more efficient than my version, but won't it fail to capture
relationships of any pre-existing classes? Seems it will only affect classes
defined after it has been loaded.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama