Part2 Rubyに学ぶ「Ruby on Railsの正体」:ITpro
def normalize_input(user_input) return case user_input when Numeric user_input # 数値はそのまま when 'inf' 1.0 / 0.0 # infは無限大 when 'a' .. 'f' user_input.hex # aからfまでの文字を16進数と解釈 when /^[0-9]+$/ user_input.to_i # 数字からなる文字列を数値化 else raise # それ以外はエラー end end
def normalize_input(user_input) return if user_input.kind_of? Numeric then user_input elsif 'inf' == user_input then 1.0 / 0.0 elsif ('a' .. 'f').include? user_input then user_input.hex elsif /^[0-9]+$/.match? user_input then user_input.to_i else raise end end
Object#===メソッドは,デフォルトでは同値演算子==を呼び出します。
このため,2番目の条件判定は,'inf' == user_inputとして機能します。
一方,Classクラスでは===メソッドはオーバーライドされ,クラスのインスタンスであるかどうかを調べる kind_of?メソッドと同様の機能を持つようになっています(図2)。これにより,最初の「クラスのインスタンスであるかどうか」という条件判定がうまくいくのです。
同様に,Range(範囲)クラスでは,範囲内であるかどうかを判定するinclude?メソッドであるかのようにオーバーライドされ,Regex(正規表現)クラスでは,マッチするかどうかを判定するmatch?であるかのようにオーバーライドされています。
Rubyの標準ライブラリは,クラスごとに適切な実装でObject#===をオーバーライドすることで,case式の柔軟な挙動を実現しています。