Automatic instantiation of subclasses

Hi!

First sorry I am a beginner ;-( What I want to do is: automatically
instantiate subclasses of a given class, say, A.

  class A
  end

  class A1 < A
  end

  class A2 <A
  end

So I want to know the names of A subclasses: A1 and A2. Then instantiate
via reflection. Is it possible?

Using ObjectSpace it is possible to know all the instantiated objects of
a class. But here no objects yet.

Thanks a lot.

···

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

class A
  class << self; attr_reader :subclasses end
  def self.inherited(x); (@subclasses ||= ) << x end
end

class A1 < A; end
class A2 < A; end

A.subclasses # => [A1, A2]
A.subclasses.map{|x| x.new} # => [#<A1:0xa7d73064>, #<A2:0xa7d73050>]

class A1b < A1; end
A1.subclasses # => [A1b]

You can use @@subclasses if you want A.subclasses to include A1b:

class A
  @@subclasses =
  def self.subclasses; @@subclasses end
  def self.inherited(x); @@subclasses << x end
end

class A1 < A; end
class A2 < A; end

A.subclasses # => [A1, A2]
A.subclasses.map{|x| x.new} # => [#<A1:0xa7d3c03c>, #<A2:0xa7d3c028>]

class A1b < A1; end
A.subclasses # => [A1, A2, A1b]

···

On Tue, Aug 08, 2006 at 06:19:12PM +0900, Kilivor Kante wrote:

First sorry I am a beginner ;-( What I want to do is: automatically
instantiate subclasses of a given class, say, A.

  class A
  end

  class A1 < A
  end

  class A2 <A
  end

So I want to know the names of A subclasses: A1 and A2. Then instantiate
via reflection. Is it possible?

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

This is a fun pattern that I use a lot.
Here is a simple code snippet using ObjectSpace:

subclasses =
ObjectSpace.each_object(Class) do |klass|
   if klass != A && klass.ancestors.include?(A)
     subclasses << klass
    end
end

# Then you can create new instances by calling new on the class
subclases.each do |klass|
   klass.new
end

Cheers,
Zev

···

On Tue, 08 Aug 2006 18:19:12 +0900, Kilivor Kante <kilivor@hotmail.com> wrote:

First sorry I am a beginner ;-( What I want to do is: automatically
instantiate subclasses of a given class, say, A.

  class A
  end

  class A1 < A
  end

  class A2 <A
  end

So I want to know the names of A subclasses: A1 and A2. Then instantiate
via reflection. Is it possible?

Using ObjectSpace it is possible to know all the instantiated objects of
a class. But here no objects yet.

Kilivor Kante wrote:

Hi!

First sorry I am a beginner ;-( What I want to do is: automatically instantiate subclasses of a given class, say, A.

  class A
  end

  class A1 < A
  end

  class A2 <A
  end

So I want to know the names of A subclasses: A1 and A2. Then instantiate via reflection. Is it possible?

   class Class
     def inherited(subclass)
       subclasses.push(subclass)
     end

     def subclasses
       @subclasses ||=
     end
   end

   class A; end
   class B < A; end
   class C < A; end

   A.subclasses => [B, C]
   instances = A.subclasses.map{|subclass| subclass.new }

Cheers,
Daniel

Sorry for answering late, I've been away for a week.

Kilivor Kante schrieb:

First sorry I am a beginner ;-( What I want to do is: automatically instantiate subclasses of a given class, say, A.

  class A
  end

  class A1 < A
  end

  class A2 <A
  end

So I want to know the names of A subclasses: A1 and A2. Then instantiate via reflection. Is it possible?

Using ObjectSpace it is possible to know all the instantiated objects of a class. But here no objects yet.

In Ruby, classes are first-class objects :wink:

   ObjectSpace.each_object( class << A; self; end ) do |c|
     p c
   end

Regards,
Pit

Mauricio Fernandez wrote:

[..]
You can use @@subclasses if you want A.subclasses to include A1b:
[..]

Thanks / gracias!!!!

···

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

Daniel Schierbeck wrote:

  class Class
    def inherited(subclass)
      subclasses.push(subclass)
    end

    def subclasses
      @subclasses ||=
    end
  end

Now that I think about it, this may be better:

   class Class
     def inherited(subclass)
       (@subclasses ||= ).push(subclass)
     end

     def subclasses
       (@subclasses ||= ).dup
     end
   end

That way you can somewhat avoid the problems given by

   A.subclasses.push(UnrelatedClass)

Cheers,
Daniel

I am sure Mauricio knows this, but just in case others don't. If you
use this particular solution a lot you might also want to call super,
because your class might inherit from another class that also wants to
use the inherited method. A simple change to fix this is:

def self.inherited(x); (@subclasses ||= ) << x; super; end

Cheers,
Zev

···

On Tue, 08 Aug 2006 18:32:24 +0900, Mauricio Fernandez <mfp@acm.org> wrote:

On Tue, Aug 08, 2006 at 06:19:12PM +0900, Kilivor Kante wrote:

So I want to know the names of A subclasses: A1 and A2. Then instantiate
via reflection. Is it possible?

class A
  class << self; attr_reader :subclasses end
  def self.inherited(x); (@subclasses ||= ) << x end
end