how to create an object of a class you don't know yet

B

Bradley, Todd

Hi, I'm just now getting into Ruby's OO-ness, and could use some advice.
I'm trying to create an object, but which specific class needs to be
determined at runtime. I figured out how to do this by creating a
string and executing it using the "eval" command, but I know there must
be an easier way. My first guess was to do something like #{answer}.new
but that didn't work.


Here's my code:


class Foo
def method1
end
end

class Bar
def method2
end
end

# Pretend this was determined at runtime
answer = "Foo"


# There must be a better way of doing this:

myobj = Object.new # Needs to exist in this scope
mystring = "myobj = #{answer}.new"

eval mystring

puts "I just created a #{myobj.class} object."




Any advice is appreciated. Thanks in advance!


Todd.
 
E

Eric Hodel

Hi, I'm just now getting into Ruby's OO-ness, and could use some
advice.
I'm trying to create an object, but which specific class needs to be
determined at runtime. I figured out how to do this by creating a
string and executing it using the "eval" command, but I know there must
be an easier way. My first guess was to do something like
#{answer}.new
but that didn't work.


Here's my code:


class Foo
def method1
end
end

class Bar
def method2
end
end

# Pretend this was determined at runtime
answer = "Foo"


# There must be a better way of doing this:

myobj = Object.new # Needs to exist in this scope
mystring = "myobj = #{answer}.new"

eval mystring

puts "I just created a #{myobj.class} object."

klass = answer.split('::').inject(Object) { |klass,const|
klass.const_get const }

myobj = klass.new

In longer terms:

answer.split('::') # for Foo::Bar::Baz nested classes/modules

answer.split('::').inject(Object) do |klass, const| # namespaces start
from Object
klass.const_get const # #inject passes the value of this expression in
# as the first arg to the block, so use that namespace
# to find the next part of the namespace
end

klass = answer.split [...] # #inject returns the last result, which will
# be a class, provided answer references a class

myobj = klass.new # instantiate an instance of the class

You can also do things like this:

KLASSES = { 'html' => HTMLWriter, 'pdf' => PDFWriter, 'plain-text' =>
TextWriter }

output = ARGV.shift

raise "invalid output type" unless KLASSES.include? output

writer = KLASSES[output].new
 
F

Francis Hwang

"new" is just a class method, and you can call class methods on classes
that aren't bound at the time of interpretation. For example:

instance = MyClass.new

is the same as

a_class = MyClass
instance = a_class.new

So you can do things like:

irb(main):001:0> classes = [ String, Hash, Array ]
=> [String, Hash, Array]
irb(main):002:0> grab_bag = classes.collect { |a_class| a_class.new }
=> ["", {}, []]



Hi, I'm just now getting into Ruby's OO-ness, and could use some
advice.
I'm trying to create an object, but which specific class needs to be
determined at runtime. I figured out how to do this by creating a
string and executing it using the "eval" command, but I know there must
be an easier way. My first guess was to do something like
#{answer}.new
but that didn't work.


Here's my code:


class Foo
def method1
end
end

class Bar
def method2
end
end

# Pretend this was determined at runtime
answer = "Foo"


# There must be a better way of doing this:

myobj = Object.new # Needs to exist in this scope
mystring = "myobj = #{answer}.new"

eval mystring

puts "I just created a #{myobj.class} object."




Any advice is appreciated. Thanks in advance!


Todd.

Francis Hwang
http://fhwang.net/
 
D

Daneel van Tonder

Hi, I'm just now getting into Ruby's OO-ness, and could use some advice.
I'm trying to create an object, but which specific class needs to be
determined at runtime. I figured out how to do this by creating a
string and executing it using the "eval" command, but I know there must
be an easier way. My first guess was to do something like #{answer}.new
but that didn't work.


Here's my code:


class Foo
def method1
end
end

class Bar
def method2
end
end

# Pretend this was determined at runtime
answer = "Foo"


# There must be a better way of doing this:

myobj = Object.new # Needs to exist in this scope
mystring = "myobj = #{answer}.new"

eval mystring

puts "I just created a #{myobj.class} object."




Any advice is appreciated. Thanks in advance!


Todd.
class GMClassManager
@@classHash = { 'CLASS_ROOM_DEFAULT' => GMRoom,
'CLASS_ROOM_LOGIN' => GMLoginRoom,
}

def GMClassManager.getRoomObject( valueClassId )
tmpClass = @@classHash[ valueClassId ]
if not tmpClass == nil
tmpClass.new
else
nil
end
end
end


This works for me
 
F

Florian Gross

Daneel said:
class GMClassManager
@@classHash = { 'CLASS_ROOM_DEFAULT' => GMRoom,
'CLASS_ROOM_LOGIN' => GMLoginRoom,
}

Using a constant instead would be nicer, I think.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top