読者です 読者をやめる 読者になる 読者になる

kitak.blog

Kみたいなエンジニアになりたいブログ

ハッシュオブジェクトに特異メソッドを定義して拡張

Ruby

こんにちは. 最近, こういうコードをたくさん書くんですよね.

@count_val['val1'] ||= 0
@count_val['val2'] ||= 0
@count_val['val3'] ||= 0
# ...

いわゆるnilカード. でも, いちいちこんなのを各プロパティごとに書くのは面倒くさい. そこで特異メソッドを定義してみました. 特異メソッドは, そのオブジェクト専用のメソッドのことです.

class << @count_val
  alias_method :org, :[]
  
  def [](name)
    self[name] = 0 unless self.has_key? name
    self.send(:org, name)
  end
end

最初はdef @count_val[]...の形で書こうと思ったのですが, []メソッド内で[]メソッドを使わないといけませんでした. こうなると, 終わりのない再帰処理になってしまうので, alias_methodを使ってオリジナルのメソッドを残しておきます. alias_methodを宣言するために特異クラスの形で記述します. 特異クラスは, そのオブジェクト専用のクラスです(詳しくはメタプログラミングRubyを参照のこと). 特異メソッドは特異クラスのインスタンスメソッドです.
メソッドを再定義して, もし存在しないプロパティならば0を代入します. その後にプロパティの値をorgメソッド(オリジナルの[]メソッド)を呼ぶことで返しています.

# 9/16追記
普通にHash#default使えよカスってかんじですね