subclasses = Array.new
## Magic code that puts all subclasses of a class in
## the subclasses array
subclasses = get_subclasses( .... )
subclasses.each { |subclass|
return subclass.new if condition == true
end
sorry I am very new to Ruby and have no idea on how to do this.
any help is appreciated.
Horacio
There are two possible approaches:
1. Find them when you need them via ObjectSpace:
>> cl = Enumerable
=> Enumerable
>> subclasses = []
=> []
>> ObjectSpace.each_object(Module) {|m| subclasses << m if
m.ancestors.include? cl}
=> 371
>> subclasses
=> [Struct::Tms, Dir, File, IO, Range, Struct, Hash, Array, String,
Enumerable]
2. Record them when they are created.
This is typically done by a variant that uses Class#inherited.
>> class Foo
>> def self.inherited(cl)
>> p cl
>> end
>> end
=> nil
>> class Bar < Foo
>> end
Bar
=> nil
Kind regards
robert
Something like this should get you started (though don't expect it to
be efficient - it basically queries every object in the system to find
the subclasses):
class A
end
class B < A
end
class C < B
end
class Class
def subclasses
class_hash = {}
ObjectSpace.each_object do |obj|
if Class == obj.class
if obj.ancestors.include? self
class_hash[obj] = true
end
end
end
class_hash.keys
end
end
p A.subclasses
#=> [C, B, A]
Regards,
Sean
class Module
def subclasses
classes = []
ObjectSpace.each_object(Module) do |m|
classes << m if m.ancestors.include? self
end
classes
end
end
Regards,
Sean
Object#kind_of?, #is_a?, #instance_of?, #type (deprecated), #class
Module#ancestors, #included_modules
Class#inherited, #superclass
MyClassname === myobj
> -----Original Message-----
> From: Sean O'Halpin [mailto:sean.o...@gmail.com]
> Sent: Monday, October 24, 2005 1:49 PM
> To: ruby-talk ML
> Subject: Re: How to find all the subclasses of a class?
>
> Incorporating Robert's suggestions, this is a bit better:
>
> class Module
> def subclasses
> classes = []
> ObjectSpace.each_object(Module) do |m|
> classes << m if m.ancestors.include? self
> end
> classes
> end
> end
>
> Regards,
>
> Sean
prettyfied:
require 'enumerator'
class Module
def subclasses
ObjectSpace.to_enum(:each_object, Module).select do |m|
m.ancestors.include?(self)
end
end
end
cheers
Simon
class Class
def inherited(subclass)
if superclass.respond_to? :inherited
superclass.inherited(subclass)
end
@subclasses ||= []
@subclasses << subclass
end
def subclasses
@subclasses
end
end
class SuperClass; end
class A < SuperClass; end
class B < SuperClass; end
class C < SuperClass; end
class D < A; end
puts SuperClass.subclasses.join(", ") # A, B, C, D
If you only need one superclass, this is more efficient:
class MyClass
def self.inherited(subclass)
if superclass.respond_to? :inherited
superclass.inherited(subclass)
end
@subclasses ||= []
@subclasses << subclass
end
def self.subclasses
@subclasses
end
end
Cheers,
Daniel
If you want to find subclasses of a *class* instead of a module, you can
pass the singleton class of the base class:
require "enumerator"
def get_subclasses(klass)
ObjectSpace.enum_for(:each_object, class << klass; self; end).to_a
end
Horacio, if you need help to decipher this code, feel free to ask.
Regards,
Pit
Cool! Didn't know this. Learn something new every day... Thanks!
Kind regards
robert
pit that's insanely cool - thanks!
-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| anything that contradicts experience and logic should be abandoned.
| -- h.h. the 14th dalai lama
===============================================================================
At Mon, 24 Oct 2005 20:05:43 +0900,
Horacio Sanson wrote in [ruby-talk:162270]:
> I want to be able to list and instatiate all subclasses of a class to create a
> Factory type pattern, I want to be able to do something like
FYI, http://www.rubyist.net/~nobu/ruby/factory.rb
--
Nobu Nakada
Same for me. I didn't know this either until today :-)
Regards,
Pit
Horacio
Monday 24 October 2005 21:30、Kroeger, Simon (ext) さんは書きました:
> m.ancestors.include?(self)