[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Automatic instantiation of subclasses

Kilivor Kante

8/8/2006 9:19:00 AM

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-....

7 Answers

Mauricio Fernández

8/8/2006 9:32:00 AM

0

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?

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]

--
Mauricio Fernandez - http://eige... - singular Ruby

Zev Blut

8/8/2006 9:36:00 AM

0

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 instantia=
te
> via reflection. Is it possible?
>
> Using ObjectSpace it is possible to know all the instantiated objects =
of
> a class. But here no objects yet.

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

subclasses =3D []
ObjectSpace.each_object(Class) do |klass|
if klass !=3D 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

Kilivor Kante

8/8/2006 9:39:00 AM

0

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

Thanks / gracias!!!!

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

Daniel Schierbeck

8/8/2006 10:28:00 AM

0

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

Daniel Schierbeck

8/8/2006 12:58:00 PM

0

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

Zev Blut

8/8/2006 1:13:00 PM

0

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

> 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 instanti=
ate
>> via reflection. Is it possible?
>
> class A
> class << self; attr_reader :subclasses end
> def self.inherited(x); (@subclasses ||=3D []) << x end
> end


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 ||=3D []) << x; super; end

Cheers,
Zev


Pit Capitain

8/13/2006 11:14:00 PM

0

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 ;-)

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

Regards,
Pit