この記事はアピリッツの技術ブログ「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.
で解決です。