引数にメソッド追加してリテラル風にするんだったら(追記)
id:takkawさんから返信を頂きました。
コメントしようかと思ったんですが長くなってしまったので、追記にしようと思ったらさらに長くなったので独立したエントリで。
特に実装側がinstance_variable_set だけで良いし。
http://d.hatena.ne.jp/takkaw/20080721/p1
これはそのまま欠点にもなって、例えばNumeric#bitが@sample_bitしか表せないのでGameRom.new(16.bit)とかには使えないんですよね。汎用性がない。
Symbolを渡しておいて実装側で処理を決定するほうが汎用的ではあります。
一方、ハッシュにしておくと、従来の通りのハッシュによる指定もできるしなー
http://d.hatena.ne.jp/takkaw/20080721/p1
そうなんですよね。
Wav.new(1.channel, 44100.hz, 16.bit) Wav.new(:channel => 1, :freq => 44100, :bit => 16)
が同義になるのが理想だと思います。
これ書いたときはHashの配列をmergeする手段がぱっと思いつかなかったのですが、良く考えると
args.inject({}){ |result, value| result.merge! value }
の一行で済みますね。
上記を踏まえて、こんな感じの実装も考えてみました。
# 仕込み class Numeric def hz ; {:freq, self} ; end def khz ; {:freq, self * 1000} ; end def bit ; {:bit, self} ; end def channel ; {:channel, self} ; end def ch ; {:channel, self} ; end end # 実際のWavクラス class Wav def initialize *args options = args.inject({}){ |result, value| result.merge! value } options.each_pair do |key, value| case key when :channel ; @channels = value when :freq ; @sample_rate = value when :bit ; @sample_bit = value end end end end
これで、Hashで渡してもメソッドで渡しても同義になるはずです。
p Wav.new(1.channel, 44100.hz, 16.bit) #=> #<Wav:0x2b2e77c @channels=1, @sample_bit=16, @sample_rate=44100> p Wav.new(44100.hz, 16.bit, 1.channel) #=> #<Wav:0x2b2e5d8 @channels=1, @sample_bit=16, @sample_rate=44100> p Wav.new(:channel => 1, :freq => 44100, :bit => 16) #=> #<Wav:0x2b2e470 @channels=1, @sample_bit=16, @sample_rate=44100>