ハマったこと
Ruby でクラス同士を比較するときに case 文だとうまくいかない
例えば User クラスがあったとして、それを case 文で判定したいとする
user = User
case user
when User
puts "User クラスです"
else
puts "User クラスではありません"
end
奇妙なことに出力されるのは "User クラスではありません" という文章になります
原因
case では内部で比較演算子 ===
が使われている
これがクラスを比較する場合、演算子の左側にインスタンスが置かれることを要求しているので以下の文は false になります
> user = User
> user === User
=> false
逆に ==
演算子であれば true になります
> user == User
=> true
公式のドキュメントを見たら確かに以下のような記述がありました
case は一つの式に対する一致判定による分岐を行います。when 節で指定された値と最初の式を評価した結果とを演算子 === を用いて比較して、一致する場合には when 節の本体を評価します。
解決方法
クラスオブジェクト同士を比較する場合は case ではなく if を使う
シンプルですがこれで解決です
比較の際には ==
演算子を使うようにしてください
user = User
if user == User
puts "User クラスです"
else
puts "User クラスではありません"
end
こうすれば正しく "User クラスです" と出力されます
インスタンスとクラスを比較する場合は通常通り ===
を使うか class
メソッドを使って比較してください
user = User.new # この場合 user は User クラスのインスタンス
if user.class == User
puts "User クラスのインスタンスです"
end
インスタンスとクラスを比較したい場合は他にも is_a?
, kind_of?
, instance_of?
などが使えます
蛇足
これまで30年生きてきて、ifとcaseは同じものだと思っていましたが、少なくとも ruby では違うようです
if と case の使い分けは単に条件式をきれいに書きたいかどうかだと思ってたのですが、こんな差異もあるんだなぁという学びを得ました