class Foo def initialize(foo, bar, baz) @foo = foo @bar = bar @baz = baz end end
は各変数を 3 回も書いてぜんぜん DRY じゃなくて嫌。
class Foo def initialize(*a) @foo, @bar, @baz = *a end end
は引数のチェックをしなくなるし、なんか嫌。
Foo = Struct.new(:foo, :bar, :baz)
はまあいいんだけど、なにか継承したいときに困るし、勝手にアクセサ定義されるし、まあなんか嫌。
ということで、こんなの考えた。
class Foo def_initialize(:@x, :@y, :@z) def foo p [@x, @y, @z] end end Foo.new(1, 2, 3).foo #=> [1, 2, 3]
ううん、微妙だ。一応以下が実装。
class Class def def_initialize(*vars) define_method(:initialize) do |*vals| if vars.size != vals.size msg = "wrong number of arguments (#{ vals.size } for #{ vars.size })" raise ArgumentError, msg end vars.zip(vals) {|var, val| instance_variable_set(var, val) } yield if block_given? end end end