1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

100万人に伝えたい!失敗を乗り超えた話を共有しよう

Ruby でクラスオブジェクト同士を比較するときは case ではなく if を使う

Last updated at Posted at 2023-08-09

ハマったこと

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 の使い分けは単に条件式をきれいに書きたいかどうかだと思ってたのですが、こんな差異もあるんだなぁという学びを得ました

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?