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.
On Tue, Aug 08, 2006 at 06:19:12PM +0900, Kilivor K. wrote:
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]
On Tue, 08 Aug 2006 18:19:12 +0900, Kilivor K. [email protected]
wrote:
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.
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
Kilivor K. wrote:
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 S. 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
On Tue, 08 Aug 2006 18:32:24 +0900, Mauricio F. [email protected]
wrote:
On Tue, Aug 08, 2006 at 06:19:12PM +0900, Kilivor K. 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
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
Sorry for answering late, I’ve been away for a week.
Kilivor K. schrieb:
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