case文やif文で型を比較したときの挙動
oscモジュールのソースを見ていて不思議なコードがあり、ちょっと仕様から調べてみた。
そのコードとはcase-whenで自動的に型を判別してくれる、というものなのだ。
それに関連していろいろテストしてみたらなかなか面白い挙動になったのでメモしておく。
case文で型による分岐
test_params = [ 99, 1024, 3.14, "apple", nil ] test_params.each do |param| case param when 99 p "#{param}" when Integer p "Integer .. #{param}" when Float p "Float .. #{param}" when String p "String .. #{param}" else p "#{param.class} .. #{param}" end end
上記コードの出力は以下のようになる。
"99" "Integer .. 1024" "Float .. 3.14" "String .. apple" "NilClass .. "
で、ポイントは、数値の分岐です。
まず、rubyにおける数値のクラス構成は「Rubyの数値 - octech」←こんな感じになっている。つまり、Fixnum < Integer < Numeric という派生関係だ。
これに関してこんなコードを実行してみた。
p "1024.class is #{1024.class}" case 1024 when Numeric p "Case-statement detects Numeric." end case 1024 when Integer p "Case-statement detects Integer." end case 1024 when Fixnum p "Case-statement detects Fixnum." end
結果は次のようになる。
"1024.class is Fixnum" "Case-statement detects Numeric." "Case-statement detects Integer." "Case-statement detects Fixnum."
つまり、case文による分岐は、派生元のスーパークラスの型でも比較がなされている、ということだ。
if文の場合
では、if文で class メソッドによる比較を行ったときはどうなるのか?と以下のコードを試してみた。
# if文ではどうなるか? if 1024.class == Numeric then p "If-statement detects Numeric" end if 1024.class == Integer then p "If-statement detects Integer" end if 1024.class == Fixnum then p "If-statement detects Fixnum" end
結果は次のようになる。
"If-statement detects Fixnum"
if文で、classメソッドによる比較を行ったときには、きっちり同じクラスでないとダメなようだ。
ということで、次の疑問が残った。
「case文におけるクラス比較のように、スーパークラスまでみて比較する方法は何かあるのだろうか?」