Creating an instance from a variable

P

Peter Hickman

I have a class like this:

class Builder
def Builder.create( klass, data )
return klass.new(data)
end
end

I want to call it as:

x = Builder.create( "Fred", data )

and get a object of type Fred.

I'm sure you can see what I am trying to do but for the life of me I
can't get the syntax correct.
 
M

Matt Mower

Hi Peter,

I have a class like this:

class Builder
def Builder.create( klass, data )
return klass.new(data)
end
end

how about:

Class Builder
def Builder.create( klass_sym, data )
klass = Class.const_get( klass_sym )
klass.new( data )
end
end

x = Builder.create( :Fred, data )

Regards,

Matt
 
L

Luc Heinrich

Peter Hickman said:
return klass.new(data)

return Kernel.const_get(klass).new(data)

Note that const_get will throw an exception if the passed class name is
unknown, so be prepared to deal with that.
 
T

Thomas Leitner

On Mon, 17 Jan 2005 19:54:47 +0900

| I have a class like this:
|
| class Builder
| def Builder.create( klass, data )
| return klass.new(data)
| end
| end

use (I have not tested this):

class Builder
def Builder.create( klass, data )
return Object.const_get(klass).new(data)
end
end

*hth*,
Thomas
 
C

CT

I'm not sure if this is what you want, but I think Kernel.const_get
can help you.
See changes below:

class Builder
def Builder.create( klass, data )
return Kernel.const_get(klass).new(data) #can pass in a string

You might wanna do some error-catching too.

HTH!
CT
 
P

Peter Hickman

Luc said:
return Kernel.const_get(klass).new(data)

Note that const_get will throw an exception if the passed class name is
unknown, so be prepared to deal with that.
Actually, trying to catch the error seems to be harder than it should
be. For example:

class Builder
def Builder.create( klass_sym, data )
begin
return Kernel.const_get( klass_sym ).new( data )
rescue
raise "There was an error"
end
end
end

Should report "There was an error" when const_get fails. However this is
untrapped.

xx.rb:26:in `const_get': uninitialized constant Bernie at Kernel (NameError)
from xx.rb:26:in `create'
from xx.rb:43

I've tried splitting this up into individual steps:

x = Kernel.const_get( klass_sym )
x.new( data )

but this makes no difference.
 
T

trans. (T. Onoma)

Or try Ruby Facets:

require 'facet/object/constant'

class Builder
def Builder.create( klass, *data )
constant( klass ).new( *data )
end
end

T.

P.S. I debate with myself that the method might be better place in Kerenl, so
it might move there in future.


| >> return klass.new(data)
| >
| >return Kernel.const_get(klass).new(data)
| >
| >Note that const_get will throw an exception if the passed class name is
| >unknown, so be prepared to deal with that.
|
| Actually, trying to catch the error seems to be harder than it should
| be. For example:
|
| class Builder
| def Builder.create( klass_sym, data )
| begin
| return Kernel.const_get( klass_sym ).new( data )
| rescue
| raise "There was an error"
| end
| end
| end
|
| Should report "There was an error" when const_get fails. However this is
| untrapped.
|
| xx.rb:26:in `const_get': uninitialized constant Bernie at Kernel
| (NameError) from xx.rb:26:in `create'
| from xx.rb:43
|
| I've tried splitting this up into individual steps:
|
| x = Kernel.const_get( klass_sym )
| x.new( data )
|
| but this makes no difference.
 
R

Robert Klemme

Peter Hickman said:
Actually, trying to catch the error seems to be harder than it should
be. For example:

class Builder
def Builder.create( klass_sym, data )
begin
return Kernel.const_get( klass_sym ).new( data )
rescue
raise "There was an error"
end
end
end

Should report "There was an error" when const_get fails. However this is
untrapped.

xx.rb:26:in `const_get': uninitialized constant Bernie at Kernel (NameError)
from xx.rb:26:in `create'
from xx.rb:43

I've tried splitting this up into individual steps:

x = Kernel.const_get( klass_sym )
x.new( data )

but this makes no difference.

You need to catch NameError.

class Builder
def Builder.create( klass_sym, data )
begin
return Kernel.const_get( klass_sym ).new( data )
rescue NameError => e
raise "There was an error: #{e}"
end
end
end


robert
 
P

Peter Hickman

Robert said:
You need to catch NameError.

class Builder
def Builder.create( klass_sym, data )
begin
return Kernel.const_get( klass_sym ).new( data )
rescue NameError => e
raise "There was an error: #{e}"
end
end
end


robert
Thanks for that, I thought that an open rescue would have caught it.
Live and learn.

Thanks
 
F

Florian Gross

Peter said:
I have a class like this:

class Builder
def Builder.create( klass, data )
return klass.new(data)
end
end

I want to call it as:

x = Builder.create( "Fred", data )

Why don't just do x = Builder.create(Fred, data)?
 
B

Bertram Scharpf

Hi,

Am Montag, 17. Jan 2005, 19:54:47 +0900 schrieb Peter Hickman:
I have a class like this:

class Builder
def Builder.create( klass, data )
return klass.new(data)
end
end

I want to call it as:

x = Builder.create( "Fred", data )

I just call

class Fred
def initialize data
...
end
end
x = Builder.create Fred, data

or even

r = Builder.create Regexp, '.*'

Bertram
 
B

Bertram Scharpf

Hi Robert,

Am Dienstag, 18. Jan 2005, 01:06:06 +0900 schrieb Robert Klemme:
Why then not "Fred.new data"?
:)

I'm porting my Make replacement Bake to Ruby and I do something
like

class Real ; ...
class Phony ; ...

b = Builder.create target, name, prereqs, cmd

where `target' is either `Real' or `Phony'.

Bertram
 
A

Archit Baweja

Hi

If you want to use strings, you could also do this (slight change)

class Builder
def Builder.create(klass_name, data)
Class.const_get(klass_name.intern).new(data)
end
end

To note is the use of "intern" method which converts a string to a
symbol

HTH
Archit
 
R

Robert Klemme

Bertram Scharpf said:
Hi Robert,

Am Dienstag, 18. Jan 2005, 01:06:06 +0900 schrieb Robert Klemme:

I'm porting my Make replacement Bake to Ruby and I do something
like

class Real ; ...
class Phony ; ...

b = Builder.create target, name, prereqs, cmd

where `target' is either `Real' or `Phony'.

??? Why can't you do

b = target.new name, prereqs, cmd

I mean, a class *is* a factory for its instances. If you don't have the
requirement that the actual class of created instances might be different or
want to keep that flexibility I don't see any added value in introducing a
method for this.

Regards

robert
 
B

Bertram Scharpf

Hi Robert,

Am Dienstag, 18. Jan 2005, 17:01:12 +0900 schrieb Robert Klemme:
??? Why can't you do

b = target.new name, prereqs, cmd

I mean, a class *is* a factory for its instances. If you don't have the
requirement that the actual class of created instances might be different
or want to keep that flexibility I don't see any added value in introducing
a method for this.

Hm, seems to be a long time since I designed this. I
remember having thought very long and thoroughly about it.

I think I didn't tell the whole truth above. My code
actually looks like

Rule.new Real, 'prog', 'prog.o', 'gcc ...'
Rule.new Phony, 'all', 'prog'
Suffix.new Real, '.o', '.c', 'gcc -c ...'

Multiple kinds of rules can instantiate multiple types of
targets. So, it is not possible to derive one from the
other.

Further, the suffix rule has to determine the target name
before it holds enough information to instantiate the target
itself.

(The whole program will be available soon.)

Bertram
 
R

Robert Klemme

Bertram Scharpf said:
Hi Robert,

Am Dienstag, 18. Jan 2005, 17:01:12 +0900 schrieb Robert Klemme:

Hm, seems to be a long time since I designed this. I
remember having thought very long and thoroughly about it.
:)

I think I didn't tell the whole truth above. My code
actually looks like

Rule.new Real, 'prog', 'prog.o', 'gcc ...'
Rule.new Phony, 'all', 'prog'
Suffix.new Real, '.o', '.c', 'gcc -c ...'

Multiple kinds of rules can instantiate multiple types of
targets. So, it is not possible to derive one from the
other.

Further, the suffix rule has to determine the target name
before it holds enough information to instantiate the target
itself.

Ok, I see.

Kind regards

robert
 

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

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,440
Latest member
YoungBorel

Latest Threads

Top