From: Jean-Hugues ROBERT Date: 2002-05-04T20:13:25+09:00 Subject: Re: dynamically assigning instance variables Hello, At 13:30 04/05/2002 +0900, you wrote: >Anyway, have a play with this one if you're >interested. It also has the advantage that it uses method_missing to >provide setters and getters for all the instance variables. > >class HashStruct > > def initialize(hash) > hash.each_pair do |key, value| > instance_eval "@#{key} = value" > end > end > > def method_missing(name, *args) > if name.to_s =~ /(.*)=/ > self.instance_eval "@#{$1} = args[0]" > else > self.instance_eval "@#{name}" > end > end > >end Harry Ohlsen This nice piece of code is solving an issue I was dealing with, about "copy constructors". This is a C++ idiom and I suspect there could be a better/different one in Ruby. However, for those interested, here is the code: # value.rb # Module that helps handling 'Value' objects and C++ style Copy Constructors # # 02/05/04, JHR, Creation # Typical synopsis: # class MyClassWithCopyConstructor # include CanValue # def initialize( some_stuff ) # return self if initValue( some_stuff) # ... init somehow differently here ... # end # ... # end # The module basically makes it easy to write copy constructors. Nota: the new # object is not a deep copy of the original, its instance variables have the # values of the original object's ones. module CanValue class Value < Hash def toValue() self end end def initValue( a_value ) return nil unless a_value.respond_to? :toValue a_value.toValue().each_pair do | var_name, value | instance_eval "#{var_name}= value" # p "Setting #{var_name} instance variable" end self end def toValue() a_value = Value.new instance_variables().each do | var_name | a_value[var_name.intern()] = instance_eval( var_name) end a_value end end # CanValue # An example, using the CanValue module. class MyClass include CanValue attr_accessor :myVar def initialize( a_value = nil ) return self if initValue( a_value) @myVar = "Hello" end def print() p @myVar; end end a = MyClass.new b = MyClass.new( a) c = a.clone() a.print; b.print; c.print a.myVar = "I am a"; b.myVar = "I am b"; c.myVar = "I am c" a.print; b.print; c.print # Apparently .clone() does a similar job: making a "copy" of a object. # However it does not work well with .new(), as can be seen here: class MyClass2 attr_accessor :myVar def initialize( some_stuff = nil ) return some_stuff.clone() if some_stuff.kind_of? self.class() @myVar = "Hello" end def print() p @myVar; end end a = MyClass2.new b = MyClass2.new( a) # Does not work c = a.clone() a.print; b.print; c.print a.myVar = "I am a"; b.myVar = "I am b"; c.myVar = "I am c" a.print; b.print; c.print # A solution is to use a MyClass.create instead of MyClass.new. This could be # another example for those who believe in "'new' considered harmful"... class MyClass3 attr_accessor :myVar def initialize() @myVar = "Hello" end def self.create( some_stuff = nil ) return some_stuff.clone() if some_stuff.kind_of? self new end def print() p @myVar; end end a = MyClass3.create b = MyClass3.create( a) c = a.clone() a.print; b.print; c.print a.myVar = "I am a"; b.myVar = "I am b"; c.myVar = "I am c" a.print; b.print; c.print Question: What the preferred idiom for creating objects in Ruby ? The C++ idioms ('new' & overloading) seems rather unpractical to me, due to the inability to overload new (or any other method, for that matter) based on the parameters. Yours, Jean-Hugues ------------------------------------------------------------------------- Web: http://hdl.handle.net/1030.37/1.1 Phone: +33 (0) 4 92 27 74 17