同値性と同一性
Rubyでは等しいか比較をする時
基本的にレシーバとなるオブジェクトのクラスにオーバーライド(再定義)された
Object#== Object#=== Object#equal?
を用います。
それぞれ等しいならtrue、異なるならfalseとなる点は同じですが、判断基準が異なります。
==
==は同値性を判断しています。
a = 'abc' b = 'abc' a == b #=>true
同値性とは文字の通り、値が等しいとtrueとなります。
上記は値は等しいですが、別のオブジェクトです
a.object_id #=>70337627390140 b.object_id #=>70337627471920
また、Integerクラス(整数)やFloatクラス(浮動小数点数)等の数値、シンボルは値が等しいと、同じオブジェクトとなります。
int = 1 int2 = 1 int.object_id #=> 3 int2.object_id #=> 3
Object#equal?
Object#equal?は同一性を判断しています。
==の例の文字列も同一性はありません
a.equal? b #=>false
同一のオブジェクトを参照している時のみtrueとなります。
c = a
a.equal? c #=>true
rubyにおいて複製などをする際、オブジェクトの要素はコピーせずにそのまま参照することがあります。
ary = %w[1 2 3] #=>["1", "2", "3"] #cloneはレシーバのオブジェクトのコピーを出力 ary2 = ary.clone ary[0].equal? ary2[0] #=> true
ary3 = %w[a b] #=> ["a", "b"] #Array#*は要素を引数の数だけ繰り返す re = ary3 * 2 #=> ["a", "b", "a", "b"] re[0].equal? re[2] #=>true ary3[0].equal? re[0] #=>true
同じオブジェクトを破壊的メソッドを使用した時、参照している全てに影響してしまいます。
#上の続き ary[0] #=>"1" #succは次の数字や文字を出力。succ!は破壊的メソッド ary[0].succ! #=>"2" ary #=>["2", "2", "3"] ary2 #=>["2", "2", "3"]
===
===は基本的に同値性で判断しますが、case文のバックで用いられるため、クラスによって==とは異なる内容の再定義がされている場合があります。
等式は可換(左右を入れ替えても結果が同じ)ですが、上記の理由で===では非可換となる場合があります。
/[a-z]+/ === 'string' #=>true 'string' === /[a-z]+/ #=>false
これはRegexpクラス(正規表現)ではRegexp#===として正規表現にマッチすればtrueとなる再定義されている。しかしStringクラスはString#==と同じ再定義しているため可換性がなくなっています。
参考