[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Creating objects from a template

David McCabe

2/9/2005 6:17:00 AM

Hi folks.

I'm pretty comfortable with Python, and I just decided to give Ruby a
shot. I'm trying to duplicate a nifty method I use in Python to
instantiate objects with properties that are loaded from a file.

My program is a war strategy game, which involves several different
types of artillery units. Each type has properties such as range,
speed, power, etc. I need to load these values from a file.

In python, my parser returns a hash of unit_type objects, where the
names of units are the keys. Each time a unit is instantiated, it
receives a unit_type object as an argument. Now here's the interesting
part: it copies the instance variables from the unit_type into itself.

class Unit(object):
def __init__(self, type):
self.type = type
self.__dict__.update(self.type.__dict__)

There's more to it than that, but that's the interesting part. So now
I can say:

my_new_unit = Unit(types["Panzer"])

And I'll get a Unit object with all the values for Panzers
initialized.

drbrain on #ruby-lang came up with this:

http://rafb.net/paste/results/lgb...

It looks like it'll do what I want. There's only one deficiency: I
would have to list out every possible proporty of a unit in two
seperate places in the source. In the python version, I don't have to
list it at all. Whatever properties are in the config file are loaded
into the object.

So, now I'm looking for any pointers on ways to do this.

Thanks!

6 Answers

Assaph Mehr

2/9/2005 6:59:00 AM

0


David McCabe wrote:
> In python, my parser returns a hash of unit_type objects, where the
> names of units are the keys. Each time a unit is instantiated, it
> receives a unit_type object as an argument. Now here's the
interesting
> part: it copies the instance variables from the unit_type into
itself.
>
> class Unit(object):
> def __init__(self, type):
> self.type = type
> self.__dict__.update(self.type.__dict__)
>
> There's more to it than that, but that's the interesting part. So now
> I can say:
>
> my_new_unit = Unit(types["Panzer"])
>
> And I'll get a Unit object with all the values for Panzers
> initialized.
>
> drbrain on #ruby-lang came up with this:
>
> http://rafb.net/paste/results/lgb...
>
> It looks like it'll do what I want. There's only one deficiency: I
> would have to list out every possible proporty of a unit in two
> seperate places in the source. In the python version, I don't have to
> list it at all. Whatever properties are in the config file are loaded
> into the object.
>
> So, now I'm looking for any pointers on ways to do this.

Suppose you have a hash of properties like this:
.. h = { :range => 100, :strength => 50 }

Then you can define at run time accessors for these properties and set
their values like this:
.. class Unit
.. def initialize properties
.. properties.each { |k, v|
.. # define accessor
.. singleton_class.send :attr_accessor, k
.. # initialize with value
.. self.instance_variable_set "@#{k}", v
.. }
.. end
.. end

Test with:
.. a = Unit.new h
.. puts a.range

You don't have to crate the accessors, but ruby treats all instance
variables as private. So unless you define them, you will not be able
to see them from outside the instance.


The #singleton_class method is a convenient shortcut, defined as:
.. class Object
.. def singleton_class
.. class << self; self; end
.. end
.. end


HTH,
Assaph

Robert Klemme

2/9/2005 9:18:00 AM

0


"David McCabe" <davemccabe@gmail.com> schrieb im Newsbeitrag
news:1107929791.839839.293300@c13g2000cwb.googlegroups.com...
> Hi folks.
>
> I'm pretty comfortable with Python, and I just decided to give Ruby a
> shot. I'm trying to duplicate a nifty method I use in Python to
> instantiate objects with properties that are loaded from a file.
>
> My program is a war strategy game, which involves several different
> types of artillery units. Each type has properties such as range,
> speed, power, etc. I need to load these values from a file.
>
> In python, my parser returns a hash of unit_type objects, where the
> names of units are the keys. Each time a unit is instantiated, it
> receives a unit_type object as an argument. Now here's the interesting
> part: it copies the instance variables from the unit_type into itself.
>
> class Unit(object):
> def __init__(self, type):
> self.type = type
> self.__dict__.update(self.type.__dict__)
>
> There's more to it than that, but that's the interesting part. So now
> I can say:
>
> my_new_unit = Unit(types["Panzer"])
>
> And I'll get a Unit object with all the values for Panzers
> initialized.
>
> drbrain on #ruby-lang came up with this:
>
> http://rafb.net/paste/results/lgb...
>
> It looks like it'll do what I want. There's only one deficiency: I
> would have to list out every possible proporty of a unit in two
> seperate places in the source. In the python version, I don't have to
> list it at all. Whatever properties are in the config file are loaded
> into the object.
>
> So, now I'm looking for any pointers on ways to do this.

You need two simple modifications: make the initialization more general
and add accessors automatically. (see file attached).

If those properties never need to change for instances, then of course
another approach applies (see access-2.rb).

Kind regards

robert


nobu.nokada

2/12/2005 2:01:00 AM

0

Hi,

At Wed, 9 Feb 2005 15:20:07 +0900,
David McCabe wrote in [ruby-talk:130214]:
> In python, my parser returns a hash of unit_type objects, where the
> names of units are the keys. Each time a unit is instantiated, it
> receives a unit_type object as an argument. Now here's the interesting
> part: it copies the instance variables from the unit_type into itself.
>
> class Unit(object):
> def __init__(self, type):
> self.type = type
> self.__dict__.update(self.type.__dict__)
>
> There's more to it than that, but that's the interesting part. So now
> I can say:
>
> my_new_unit = Unit(types["Panzer"])
>
> And I'll get a Unit object with all the values for Panzers
> initialized.

What about:

module Unit
end

my_new_unit = types["Panzer"].extend(Unit)

--
Nobu Nakada


nobu.nokada

2/12/2005 3:26:00 AM

0

Hi,

At Sat, 12 Feb 2005 11:00:39 +0900,
nobu.nokada@softhome.net wrote in [ruby-talk:130571]:
> my_new_unit = types["Panzer"].extend(Unit)

Forgot ".new"

my_new_unit = types["Panzer"].new.extend(Unit)

--
Nobu Nakada


David McCabe

2/12/2005 3:42:00 AM

0

Robert's solution seems to do exactly what I want. Hurrah!

The only thing I'm changing is making a hash with the new classes so
that I can instantiate them easily given their names:

Object.const_set klass_name, klass
kinds[klass_name.intern] = klass

called_for = :LongRange
p kinds[called_for].new

If this isn't the Right Thing in ruby, any pointers on better ways to
do it would be appreciated.

Thank you all!

Robert Klemme

2/12/2005 12:52:00 PM

0


"David McCabe" <davemccabe@gmail.com> schrieb im Newsbeitrag
news:1108179699.496561.195290@l41g2000cwc.googlegroups.com...
> Robert's solution seems to do exactly what I want. Hurrah!
>
> The only thing I'm changing is making a hash with the new classes so
> that I can instantiate them easily given their names:
>
> Object.const_set klass_name, klass
> kinds[klass_name.intern] = klass
>
> called_for = :LongRange
> p kinds[called_for].new
>
> If this isn't the Right Thing in ruby, any pointers on better ways to
> do it would be appreciated.

IMHO you don't need the hash. That's duplicating efforts the interpreter
does for you already. You can just use the class name:

# called_for can be a Symbol or String
Object.const_get(called_for).new

Kind regards

robert