ホーム DoRuby case文の落とし穴

case文の落とし穴

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

初めまして、エンジニア一年目のサンドリバー砂川です。

今回は開発中につまずいたcase文の挙動について解説をします。

こんな感じのcase文を考えてみます。

class Obj
  class Foo
  end

  class Bar
  end
end

obj = Obj::Foo

case obj
  when Obj::Foo
    puts "obj is Foo."
  when Obj::Bar
    puts "obj is Bar"
  else
    puts "obj is unknown...."
end

スクリプトを実行してみると

obj is unknown....

何故か比較がうまいこと出来てません。

実はcase文ではこんな風に比較が行われます。

case obj
  when Obj::Foo
end
↓
if Obj::Foo === obj

問題は演算子===で、こいつは呼び出したオブジェクトの型によって挙動が変わります。

例えばString#===なら==と同じ挙動ですが、Class#===の場合はkind_of?と同じ挙動になります。

kind_of?メソッドは、引数が呼び出したオブジェクトのインスタンスの場合にtrueを返します。

今回のコードではobj = Obj::Fooとクラスオブジェクト自体を代入していたのでfalseになってしまったんですね。

なので解決策として、objにインスタンスを代入する。

obj = Obj::Foo.new

あるいはto_sメソッドを利用して比較する。

case obj.to_s
  when Obj::Foo.to_s
    puts "obj is Foo."
  when Obj::Bar.to_s
    puts "obj is Bar"
  else
    puts "obj is unknown...."
end

obj is Foo.

で解決です。

記事を共有

最近人気な記事