instance from class name?

A

Alexander Lamb

Hello,

I am new to this list (and language) but I didn't find my answer from =20=

the documentation available.

I simply would like to do something like:

myObject =3D class.fromName("a_class_name").new

I can do this in Java and Objective-C but didn't find how in Ruby. =20
The idea is to have some configuration files for an activity which =20
contain a class name to instantiate depending on the activity.

Many thanks (and sorry if this is an obvious question),
--
Alexander Lamb
Service d'Informatique M=E9dicale
H=F4pitaux Universitaires de Gen=E8ve
(e-mail address removed)
+41 22 372 88 62
+41 79 420 79 73
 
D

David A. Black

Hi --

Hello,

I am new to this list (and language) but I didn't find my answer from the
documentation available.

I simply would like to do something like:

myObject = class.fromName("a_class_name").new

my_object = Object.const_get("MyClass").new

or some variation of that.


David
 
E

ES

David said:

Classes are stored as constants in ruby. Witness Mr. Black's solution:
my_object = Object.const_get("MyClass").new

or some variation of that.

That works; however, if your class name looks like SomeModule::SomeClass,
you will need to be a bit fancier because const_get only looks for constants
in the current class or module (the top-level Object instance is the default):

class_name.split('::').inject(Object) {|parent, obj| parent.const_get obj}.new

#split creates an array ['SomeModule', 'SomeClass'], which we iterate over
using #inject. In the #inject block, the parent will always be the parent
class or module in which we look for the constant and obj is the next class
or module name. The Object is passed in as the initial parent object. the
parent.const_get obj sequence then looks like

Object.const_get 'SomeModule' => => SomeModule.const_get 'SomeClass'

There may be a method to directly get the class in the future whether it is
nested or not. In the meanwhile, you can stick the above code in a method
if you will be using it a lot.

Also, you can always use #eval:

obj = eval(class_name).new

Only, of course, if you trust the source of the class_name String. The
former method is preferred, though.

E
 
C

Christophe Grandsire

En r=E9ponse =E0 ES :
=20
That works; however, if your class name looks like SomeModule::SomeClas= s,
you will need to be a bit fancier because const_get only looks for=20
constants
in the current class or module (the top-level Object instance is the=20
default):
=20
class_name.split('::').inject(Object) {|parent, obj| parent.const_get= =20
obj}.new
=20

Oh... my...!!! I thought I understood how inject works, but never would=20
I have guessed that it was capable of such nifty things!!! This is... wow=
!
#split creates an array ['SomeModule', 'SomeClass'], which we iterate o= ver
using #inject. In the #inject block, the parent will always be the pare= nt
class or module in which we look for the constant and obj is the next c= lass
or module name. The Object is passed in as the initial parent object. t= he
parent.const_get obj sequence then looks like
=20
Object.const_get 'SomeModule' =3D> =3D> SomeModule.const_get 'SomeCla= ss'
=20

When you explain it like that it makes perfect sense. But still... wow!!!
--=20
Christophe Grandsire (who's falling in love with Ruby again :) ).

http://rainbow.conlang.free.fr

You need a straight mind to invent a twisted conlang.
 
A

Alexander Lamb

Thanks for those pointers. The first suggestion worked and since I =20
can trust the String of the name of the class, it is ok.

However, I didn't find it in the documentation of the Object class. =20
I started on ruby-lang.org then was brought to rubycentral for the =20
reference.
Is there another complete reference for ruby 1.8.x? (I am running on =20
MacOSX 10.4.2).

Thanks,
--
Alexander Lamb
Service d'Informatique M=E9dicale
H=F4pitaux Universitaires de Gen=E8ve
(e-mail address removed)
+41 22 372 88 62
+41 79 420 79 73





David said:

Classes are stored as constants in ruby. Witness Mr. Black's solution:

my_object =3D Object.const_get("MyClass").new
or some variation of that.

That works; however, if your class name looks like =20
SomeModule::SomeClass,
you will need to be a bit fancier because const_get only looks for =20
constants
in the current class or module (the top-level Object instance is =20
the default):

class_name.split('::').inject(Object) {|parent, obj| =20
parent.const_get obj}.new

#split creates an array ['SomeModule', 'SomeClass'], which we =20
iterate over
using #inject. In the #inject block, the parent will always be the =20
parent
class or module in which we look for the constant and obj is the =20
next class
or module name. The Object is passed in as the initial parent =20
object. the
parent.const_get obj sequence then looks like

Object.const_get 'SomeModule' =3D> =3D> SomeModule.const_get = 'SomeClass'

There may be a method to directly get the class in the future =20
whether it is
nested or not. In the meanwhile, you can stick the above code in a =20
method
if you will be using it a lot.

Also, you can always use #eval:

obj =3D eval(class_name).new

Only, of course, if you trust the source of the class_name String. The
former method is preferred, though.


E
 
C

Christophe Grandsire

En r=E9ponse =E0 Alexander Lamb :
=20
However, I didn't find it in the documentation of the Object class. I= =20
started on ruby-lang.org then was brought to rubycentral for the =20
reference.
Is there another complete reference for ruby 1.8.x? (I am running on =20
MacOSX 10.4.2).
=20

http://www.ruby-doc.org/
However, the best way is to use ri, the built-in documentation system=20
for Ruby. Just type ri ClassOrModuleName#method to get the documentation=20
for that instance method (without the #method, you get the documentation=20
for the class or module itself, with lists of constants, class or module=20
methods and instance methods, and for class or module methods the syntax=20
is IIRC ri ClassOrModuleName::class_or_module_method).

But anyway, const_get isn't defined in Object but in Module. When you=20
call Object.const_get, you are calling an instance method of the object=20
"Object", which is an object of class "Class". Since Class inherits from=20
Module, it inherits its instance method "const_get", which can thus be=20
called on any object of class "Class", i.e. any class.

If you don't really understand it, do not fear. It took me a while to=20
get it too. Just remember that in Ruby everything is an object, and that=20
includes classes themselves :) . So you can send methods to them too.
--=20
Christophe Grandsire.

http://rainbow.conlang.free.fr

You need a straight mind to invent a twisted conlang.
 
D

David A. Black

Hi --

Classes are stored as constants in ruby. Witness Mr. Black's solution:


That works; however, if your class name looks like SomeModule::SomeClass,
you will need to be a bit fancier because const_get only looks for constants
in the current class or module (the top-level Object instance is the
default):

class_name.split('::').inject(Object) {|parent, obj| parent.const_get
obj}.new

Like Kernel#singleton_class, this is one of those things that gets
written again and again, ad hoc. I wonder if it might be a candidate
for a permanent modification to const_get....


David
 
E

ES

David said:
Hi --




Like Kernel#singleton_class, this is one of those things that gets
written again and again, ad hoc. I wonder if it might be a candidate
for a permanent modification to const_get....

If only :) Although I think that it might be more appropriate to have
something like ObjectSpace.const_get for that use.

E
 
A

Alexander Lamb

Ah, I understand. Simply a class method (like in Objective-C). I just =20=

wasn't careful about the fact in inherited from Module (the class =20
object hierarchy). This can be difficult to understand for Java =20
developer who don't have real class objects and where static =20
functions are not inherited.

Thanks,
--
Alexander Lamb
Service d'Informatique M=E9dicale
H=F4pitaux Universitaires de Gen=E8ve
(e-mail address removed)
+41 22 372 88 62
+41 79 420 79 73
 
C

Christophe Grandsire

Selon Alexander Lamb said:
Ah, I understand. Simply a class method (like in Objective-C).

That's how it comes out yes :) . I guess I could have said it just that w=
ay, but
then you'd still wonder why it was not in the documentation for Object :)=
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top