💭

【Ruby】equal?, eql?, ==, === の違い

に公開

TL;DR

  • equal? : object_idの比較
  • eql? : 型を含め値を比較
  • == : 型は含めず値を比較
  • === : 所属性の比較

equal?

object_idが等しいかどうかを比較している。

a = "hello"
b = "hello"
c = a

# 値は同じだが、参照が異なるためfalse
puts a.equal?(b) # false

# 参照が同じなのでtrue
puts a.equal?(c) # true

# Stringはミュータブルなので、同じ値のStringは別々のオブジェクトIDを持つ
puts "hoge".equal?("hoge") # false

# Integerはイミュータブルなので、同じ値のIntegerは同じオブジェクトIDを持つ(nilやbooleanなども同じ)
puts 111.equal?(111) # true

eql?

オブジェクトの値を型も含めて同じかどうか比較している。

a = "hello"
b = "hello"

# 値が同じなのでtrue
puts a.eql?(b) # true

# ==との違い
a = 1
b = 1.0

# 値は同じに見えるが、クラスはIntegerとFloatで異なるためfalse
puts a.eql?(b) # false
puts a == b # true

Hashのkeyの比較はeql?で行われている。

# それぞれのkeyはeql?でないため、このようなHashが存在しうる
hash = {1 => "aaa", 1.0 => "bbb", "hoge" => "ccc", :hoge => "ddd"}
puts hash # {1=>"aaa", 1.0=>"bbb", "hoge"=>"ccc", :hoge=>"ddd"}

===

左辺が右辺を含むかどうかを判定している(範囲、クラス、正規表現など)。

puts (1..10) === 5    # true
puts Integer === 5    # true
puts /\d+/ === "123"  # true

case文のwhen句ではこの比較で分岐を行っている。

==

オブジェクトの値が等しいかどうかを判定している。
人間にはこれが一番直感的。

a = "hello"
b = "hello"

# 値が同じなのでtrue
puts a == b # true

# eql?と異なり、型の変換を行なって同値性を比較
a = 1
b = 1.0
puts a == b # true

参考

Discussion