同値性と同一性
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#==
と同じ再定義しているため可換性がなくなっています。
参考