Rubyのinitialize
init.rb
class User
attr_reader :name, :income
def initialize(name, income)
@name = name
@income = income
end
def real_user?
@income > 10_000_000
end
end
これを
init2.rb
class User
attr_reader :name, :income
def initialize(@name, @income)
def real_user?
@income > 10_000_000
end
end
こんなふうに書きたいというのはRuby(に限りませんが)を書いていると考えたことがあるかと思います
参考:http://melborne.github.io/2013/09/27/auto-attr-set-in-ruby/
やりました
ご存知の通りRubyの自由度は高いです
なので、なんとかできないかと試してみたところ ……
auto_init.rb
class Hoge
extend AutoInit
def_initialize :arg1, :arg2
def show
p [@arg1, @arg2]
end
end
hoge = Hoge.new 1, 2
hoge.show # => [1, 2]
できました
…… はい、見ての通りクラスマクロ的ななにかです
def initialize ではなく def_initialize という名前のクラスメソッドですね
せっかくなのでさらについでに
auto_init2.rb
class Fuga
extend AutoInit
def_initialize :arg1, :arg2 do |arg3|
@arg3 = arg3.upcase
end
def show
p [@arg1, @arg2, @arg3]
end
end
fuga = Fuga.new 'hoge', 'fuga', 'piyo'
fuga.show # => ["hoge", "fuga", "PIYO"]
こんなふうにただの代入以外にもなにかしたい場合にも対応
実装
auto_init_module.rb
module AutoInit
def def_initialize(*names)
class_eval do
define_method :initialize do |*args|
names.each { |name| instance_variable_set("@#{name}", args.shift) }
instance_exec(*args, &proc) if block_given?
end
end
end
end
こんな感じです、これだけです
def_initialize実行時点でinitializeをdefine_methodで定義しています
試してみたらできたといった感じかつやや黒魔術風味なので、変なバグがありそうな気もします
今の所わかっているのは、ベースがProcであるため、変数が足りないor多い場合もエラーにならず通ってしまうことくらいですか
なんやかんやすればなんとかなるとは思いますが、ちょっとした思いつきにそこまでする気力がありませんでした …… なのでgemにしたり等の予定はないです
お付き合い、ありがとうございました