From: Robert Klemme Date: 2005-02-09T18:20:07+09:00 Subject: Re: Creating objects from a template ------=_NextPart_000_003A_01C50E90.A71ECBE0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit "David McCabe" 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/lgb4xv42.html > > 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 ------=_NextPart_000_003A_01C50E90.A71ECBE0 Content-Type: application/octet-stream; name="access-2.rb" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="access-2.rb" class ArtilleryUnit=0A= =0A= attr_reader :range=0A= =0A= ##=0A= # Metaprograming to get the right constant (our subclass' DEFAULTS)=0A= =0A= def self.defaults=0A= const_get 'DEFAULTS'=0A= end=0A= =0A= ##=0A= # So #initialize doesn't look so lame=0A= =0A= def defaults=0A= self.class.defaults=0A= end=0A= =0A= end=0A= =0A= # load config, pretend it comes back as a hash=0A= =0A= # class name # default for class=0A= defaults =3D { 'LongRange' =3D> { :range =3D> 5, :size =3D> 10 } }=0A= # ^^^^^^ a Symbol=0A= =0A= defaults.each do |klass_name, defaults|=0A= =0A= # Create the new class=0A= =0A= klass =3D Class.new(ArtilleryUnit) do=0A= # setup DEFAULTS constant=0A= const_set 'DEFAULTS', defaults=0A= =0A= # create accessors=0A= defaults.each do |k,v|=0A= define_method(k){ v }=0A= end=0A= end=0A= =0A= # add klass_name klass to the toplevel namespace (rooted at Object in = Ruby)=0A= Object.const_set klass_name, klass=0A= end=0A= =0A= p LongRange.ancestors=0A= p LongRange::DEFAULTS=0A= p LongRange.new=0A= p LongRange.new.range=0A= p LongRange.new.public_methods.grep /range|size/=0A= ------=_NextPart_000_003A_01C50E90.A71ECBE0 Content-Type: application/octet-stream; name="access.rb" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="access.rb" class ArtilleryUnit=0A= =0A= attr_reader :range=0A= =0A= ##=0A= # Metaprograming to get the right constant (our subclass' DEFAULTS)=0A= =0A= def self.defaults=0A= const_get 'DEFAULTS'=0A= end=0A= =0A= ##=0A= # So #initialize doesn't look so lame=0A= =0A= def defaults=0A= self.class.defaults=0A= end=0A= =0A= def initialize=0A= # generalized initialization=0A= defaults.each do |k, v|=0A= send "#{k}=3D", v=0A= end=0A= end=0A= =0A= end=0A= =0A= # load config, pretend it comes back as a hash=0A= =0A= # class name # default for class=0A= defaults =3D { 'LongRange' =3D> { :range =3D> 5, :size =3D> 10 } }=0A= # ^^^^^^ a Symbol=0A= =0A= defaults.each do |klass_name, defaults|=0A= =0A= # Create the new class=0A= =0A= klass =3D Class.new(ArtilleryUnit) do=0A= # setup DEFAULTS constant=0A= const_set 'DEFAULTS', defaults=0A= =0A= # create accessors=0A= defaults.each do |k,|=0A= attr_accessor k=0A= end=0A= end=0A= =0A= # add klass_name klass to the toplevel namespace (rooted at Object in = Ruby)=0A= Object.const_set klass_name, klass=0A= end=0A= =0A= p LongRange.ancestors=0A= p LongRange::DEFAULTS=0A= p LongRange.new=0A= p LongRange.new.range=0A= p LongRange.new.public_methods.grep /range/=0A= ------=_NextPart_000_003A_01C50E90.A71ECBE0--