The code below uses instance_exec from ruby 1.9. It will still work
under ruby 1.8 as long as you don't give a block to the #init method.
Gary Wright
module Init
def init(*syms, &iproc)
define_method(:initialize) {|*x|
raise ArgumentError, "wrong number of arguments: #{x.size} for #{syms.size}" if x.size != syms.size
syms.zip(x).each { |sym, val|
instance_variable_set("@#{sym}", val)
}
instance_exec(*x, &iproc) if iproc
}
end
end
class A
extend Init
init :a, :b, :c, :d
end
a = A.new(1,2,3,4)
p a.instance_variables # ["@b", "@a", "@c", "@d"]
a.instance_variables.each { |n|
puts "#{n} = #{a.instance_variable_get(n)}"
}
class Object
extend Init
end
class B
attr :attr1, :attr2
init :attr1, :attr2
end
b = B.new('foo', 'bar')
p b.attr1 # 'foo'
p b.attr2 # 'bar'
class C
init :c, :d do
puts "@c is #{@c}"
puts "@d is #{@d}"
end
end
C.new(3,4) # @c is 3
# @d is 4
begin
C.new(5) # argument error
rescue
p $!
end
···
On Jan 18, 2007, at 5:06 PM, Gregory Brown wrote:
BUT... it's be okay if you could build this as a module, I think.
Then you could just include it in a class to get the behavior when it
is appropriate.