equal?、eql?、===、==? の違いは何ですか? 質問する

equal?、eql?、===、==? の違いは何ですか? 質問する

私はこれら 4 つのメソッドの違いを理解しようとしています。デフォルトでは、両方のオペランドがまったく同じオブジェクトを参照する場合に true を返す==メソッドが呼び出されることはわかっています。equal?

===デフォルトでは も を呼び出し、==これがequal?... を呼び出します。では、これら 3 つのメソッドがすべてオーバーライドされていない場合は、 とまったく同じことを行うのでしょ=====equal??

次は ですeql?。これは何をするのでしょうか (デフォルトでは)? オペランドのハッシュ/ID を呼び出しますか?

Ruby にはなぜこれほど多くの等号があるのでしょうか? それらは意味的に異なるはずなのでしょうか?

ベストアンサー1

私は大いに引用するつもりだオブジェクトのドキュメントここに素晴らしい説明があると思うので、ぜひ読んでみてください。また、他のクラスでオーバーライドされているこれらのメソッドのドキュメントも読んでみてください。

補足: さまざまなオブジェクトでこれらを自分で試してみたい場合は、次のようにします。

class Object
  def all_equals(o)
    ops = [:==, :===, :eql?, :equal?]
    Hash[ops.map(&:to_s).zip(ops.map {|s| send(s, o) })]
  end
end

"a".all_equals "a" # => {"=="=>true, "==="=>true, "eql?"=>true, "equal?"=>false}

==— 一般的な「平等」

オブジェクト レベルでは、と が同じオブジェクトである==場合にのみ true を返します。通常、このメソッドは、クラス固有の意味を提供するために、子孫クラスでオーバーライドされます。objother

これは最も一般的な比較であり、したがって、クラスの作成者として、2 つのオブジェクトが「等しい」かどうかを判断する最も基本的な場所です。

===— 大文字と小文字の区別

Object クラスの場合、実質的には を呼び出すのと同じです#==が、通常は子孫によってオーバーライドされ、case ステートメントで意味のあるセマンティクスが提供されます。

これは非常に便利です。興味深い実装の例===:

  • 範囲
  • 正規表現
  • Proc (Ruby 1.9 の場合)

次のようなことが可能になります:

case some_object
when /a regex/
  # The regex matches
when 2..4
  # some_object is in the range 2..4
when lambda {|x| some_crazy_custom_predicate }
  # the lambda returned true
end

見る私の答えはここにありますcase+によってコードがいかに簡潔になるかを示す良い例ですRegex。もちろん、独自の===実装を提供することで、カスタム セマンティクスを実現できますcase

eql?Hash平等

メソッドは、 と が同じハッシュ キーを参照しているeql?場合に true を返します。これは、 がメンバーの等価性をテストするために使用されます。クラスのオブジェクトの場合は と同義ですサブクラスは通常、オーバーライドされたメソッドにエイリアスすることでこの伝統を引き継ぎますが、例外もあります。たとえば、 型は 間で型変換を実行しますが、 間では実行しないため、次のようになります。objotherHashObjecteql?==eql?==Numeric==eql?

1 == 1.0     #=> true
1.eql? 1.0   #=> false

したがって、独自の用途に合わせてこれをオーバーライドすることも、オーバーライドして2 つのメソッドが同じように動作するように==使用することもできます。alias :eql? :==

equal?— アイデンティティ比較

とは異なり==equal?メソッドはサブクラスによってオーバーライドされるべきではありません。このメソッドは、オブジェクトの ID を決定するために使用されます (つまり、a.equal?(b)aと同じオブジェクトである場合に限りますb)。

これは実質的にポインタの比較です。

おすすめ記事