From: Eric Hodel Date: 2004-12-04T03:55:59+09:00 Subject: Re: how to create an object of a class you don't know yet On 03 Dec 2004, at 10:44, Bradley, Todd wrote: > 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