Ruby の文字列比較 [eql?, equal?, ==, ===]
の使い分けを汗臭く説明します
概要
Ruby の文字列比較 [eql?, equal?, ==, ===]
の使い分け ( ) について
汗臭い成分はここまで。
内容を読む前に
又その話かよ と思ったあなた。
はい、その話です。
すでに理解している方は特に読む意味がない記事です。
自分が未だに、この部分を覚えていなくて
「 あれ? eql? と equal? ってどっちがどっちだっけ?」
と、都度検索しているので、
1 回自分でまとめ直したいと思いました。
同値性
Images
1 2
1 1
1 3
eql?
String#eql?
は、同値性の比較を行う。
文字列の内容が等しければ別のオブジェクトでも true を返却する。
hoge = 'hoge'
puts hoge.eql?(hoge) # => true
puts hoge.eql?('hoge') # => true
Hash のクラス内での比較に使われる。
hash = {}
hash[hoge] = 'test'
puts hash[hoge] # => test
puts hash['hoge'] # => test
==
String#==(other)
も String#eql?
と同様に同値性の比較を行う。
ただし、 other が String 以外だった場合、
-
other#to_str
があれば、other == self
で比較 - それ以外は false を返却
する点が異なる。
hoge = 'hoge'
puts hoge == (hoge) # => true
puts hoge == ('hoge') # => true
hash = {}
hash[hoge] = 'test'
puts hash[hoge] # => test
puts hash['hoge'] # => test
class Age
def initialize(age)
@age = age
end
def to_str
@age.to_s
end
def ==(other)
self.to_str == other
end
end
puts '20'.eql?(Age.new(20)) # => false
puts '20' == Age.new(20) # => true
===
String#===(other)
の機能面は String#==(other)
と同じ。
用途の違いがあり、
String#===(other)
は case 文で暗黙的に使用されている。
def test
%w(hoge hige hage hoo).each do |text|
ret = case text
when 'hoge' then 'ほげ'
when 'hige' then 'ひげ'
when 'hage' then 'はげ'
else text
end
puts ret
end
end
test
class String
# override して、呼びだされていることを確認
def ===(other)
puts "**#{other}**"
end
end
test
- 出力
ほげ
ひげ
はげ
hoo
**hoge**
**hoge**
**hoge**
hoge
**hige**
**hige**
**hige**
hige
**hage**
**hage**
**hage**
hage
**hoo**
**hoo**
**hoo**
hoo
同一性
Images
1 2
1 1
1 3
equal?
内部的には Object#equal? が呼び出されています。
Object#equal?
は同一性をチェックします。
内部的には Object#object_id
を比較しています。
同じ文字列でも、同一のオブジェクトでなければ false になります。
hoge1 = 'hoge'
hoge2 = 'hoge'
puts hoge1.object_id # => 12887137880
puts hoge2.object_id # => 12887137860
puts hoge1.equal?(hoge2) # => false
puts hoge1.equal?(hoge1) # => true
使い分け表
Method | 同値性 | 同一性 | 他オブジェクトの比較 | case 文 |
---|---|---|---|---|
eql? | ||||
== | ||||
=== | ||||
equal? |