引数をハッシュにするより専用クラスを作って(ry

Rubyではメソッドの引数にハッシュを使う場合があります。
例えば、以下はwebrickでHTTPサーバを作る場合です。

s = HTTPServer.new(
  :Port            => 2000,
  :DocumentRoot    => Dir::pwd + "/htdocs"
)


引数にハッシュを使うメリットとして
引数の順番が関係なくなり(順番を覚えなくて良い)、
見た目にも用途が明らかとなるため
メソッドを使う場合やコードを読み返す場合に有利っちゅう訳ですね。


用途限定ですが、それをもう少し改善できる
ネタを思いついたので作ってみました。


具体的にどういうものかって言いますと
現在、作っているWavクラス(Wavファイルを読み書きする)を
使って説明します。

# 単位クラスを仕込む
class Freq
  def initialize( freq ) ; @freq = freq ; end
  def to_i               ; @freq        ; end
end

class Bit
  def initialize( bit ) ; @bit = bit    ; end
  def to_i              ; @bit          ; end
end

class Channel
  def initialize( ch )  ; @ch = ch      ; end
  def to_i              ; @ch           ; end
end

# Numericからサクッと作れるように仕込む
class Numeric
  def hz      ; Freq.new( self )        ; end
  def bit     ; Bit.new( self )         ; end
  def channel ; Channel.new( self )     ; end
end

# 実際のWavクラスの初期化(抜粋)
class Wav 
  def initialize( *args )
   args.each { |arg|
      case arg 
      when Channel ; @channels    = arg.to_i 
      when Freq    ; @sample_rate = arg.to_i
      when Bit     ; @sample_bit  = arg.to_i
      end 
    }
  end
end


こうしておくと、以下のように書けて
ハッシュを使うよりも中括弧とか=>が無い分、
少しだけ短く書けます。

Wav.new 1.channel, 44100.hz, 16.bit


もちろん引数の順番も関係無いです。
上のコードは下のコードと等価です。

Wav.new 44100.hz,16.bit, 1.channel 


特殊な場合(引数が全て数値で単位が定義できる場合とか)にしか
使えないかもしれませんが覚えておくと良いのではないでしょうか?
もしくは、他にもこういうコードってあったりするのかなー??


追記:
毎度〜、rubikitchさんに添削トラバいただきました。
ありがとうございました。


=> 専用クラスを作ってキーワード引数の代わりにする - http://rubikitch.com/に移転しました


DRY化は勉強になりました。
次回のリファクタリングの時に仕込みたいなぁ。。


「同じ単位の引数が複数ある場合は使えない」とのご指摘は
まったくその通りで、用途限定ネタになってしまいますね。


active-supportと一緒に使われることはとりあえず想定していませんけど
常にrequireしているactive-support大好きっ子とかって
いまどきはいたりするのかいなー?