Dynamically creating subclasses

Hi,

I have to dynamically create a number of classes with different names.
All of them have to inherit from the same subclass.

I tried the following:

eval(class myName < ParentClass; end) where myName is a String
dynamically set together
or the same without eval.

In fact i succeeded in creating objects of the new classes (myName.new)
and the name seems to be set right, but the instantiation does not call
the parents constructor.

Can you point to my mistake?

Thanks
sun

Hi Sun,

How about this?

1.9.3p194 :001 > class A; def initialize; puts “new A”; end; end
=> nil
1.9.3p194 :003 > name = “X”
=> “X”
1.9.3p194 :007 > Object.const_set name, Class.new(A)
=> X
1.9.3p194 :008 > X
=> X
1.9.3p194 :009 > X.new
new A
=> #<X:0x007fad242a1448>
1.9.3p194 :010 >

On Wed, Oct 24, 2012 at 12:25 PM, The S. [email protected] wrote:

I have to dynamically create a number of classes with different names.

All of them have to inherit from the same subclass.

I tried the following:

eval(class myName < ParentClass; end) where myName is a String

Guess that’s a typo, make sure the string is a constant name, the class
keyword does not accept identifiers that start in lowercase.

dynamically set together
or the same without eval.

The way to do this using APIs would go through Class.new and const_set,
but
I believe that eval approach is just fine and more obvious to the reader
of
the code.

In fact i succeeded in creating objects of the new classes (myName.new)

and the name seems to be set right, but the instantiation does not call
the parents constructor.

If MyName has an initialize method, it must call super by hand somewhere
to
get the parent’s run.

On Wed, Oct 24, 2012 at 2:52 PM, The S. [email protected] wrote:

Thanks to Arlen andXavier,

I now got it working, using the non eval approach.

name = “DynamicName1”
class = Class.new(ParentClass)

Won’t work because “class” is one of the few keywords of Ruby:

$ ruby19 -ce ‘class = Class.new(String)’
-e:1: syntax error, unexpected ‘=’
class = Class.new(String)
^

Object.const_set name, class
class.new

Great to be able to do this!

Please don’t. It’s no use to assign the name to a constant because if
you do not know names beforehand (i.e. when writing the program) as
seems to be the case here you need some form of lookup anyway. You
could use eval again, but a more simpler and robust approach (because
it avoids name clashes) is this:

dyn_classes = {}
name = “DynamicName1”
dyn_classes[name] = Class.new(ParentClass)

Btw, these classes are fairly useless because the only distinguishing
factor is the name. You’d also have to generate custom methods for
each of those. What is the purpose of these generated classes?

Cheers

robert

Thanks to Arlen andXavier,

I now got it working, using the non eval approach.

name = “DynamicName1”
class = Class.new(ParentClass)
Object.const_set name, class
class.new

Great to be able to do this!

sun