I am trying to understand the difference between these four methods. I know by default that ==
calls the method equal?
which returns true when both operands refer to exactly the same object.
===
by default also calls ==
which calls equal?
... okay, so if all these three methods are not overridden, then I guess ===
, ==
and equal?
do exactly the same thing?
Now comes eql?
. What does this do (by default)? Does it make a call to the operand's hash/id?
Why does Ruby have so many equality signs? Are they supposed to differ in semantics?
Unlike the == operator which tests if both operands are equal, the equal method checks if the two operands refer to the same object. This is the strictest form of equality in Ruby. In the example above, we have two strings with the same value. However, they are two distinct objects, with different object IDs.
equals() is a method of Object class. == should be used during reference comparison. == checks if both references points to same location or not. equals() method should be used for content comparison.
The main difference between the == and === operator in javascript is that the == operator does the type conversion of the operands before comparison, whereas the === operator compares the values as well as the data types of the operands.
== is used for comparison between two variables irrespective of the datatype of variable. === is used for comparision between two variables but this will check strict type, which means it will check datatype and compare two values.
I'm going to heavily quote the Object documentation here, because I think it has some great explanations. I encourage you to read it, and also the documentation for these methods as they're overridden in other classes, like String.
Side note: if you want to try these out for yourself on different objects, use something like this:
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}
==
— generic "equality"At the Object level,
==
returns true only ifobj
andother
are the same object. Typically, this method is overridden in descendant classes to provide class-specific meaning.
This is the most common comparison, and thus the most fundamental place where you (as the author of a class) get to decide if two objects are "equal" or not.
===
— case equalityFor class Object, effectively the same as calling
#==
, but typically overridden by descendants to provide meaningful semantics in case statements.
This is incredibly useful. Examples of things which have interesting ===
implementations:
So you can do things like:
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
See my answer here for a neat example of how case
+Regex
can make code a lot cleaner. And of course, by providing your own ===
implementation, you can get custom case
semantics.
eql?
— Hash
equalityThe
eql?
method returns true ifobj
andother
refer to the same hash key. This is used byHash
to test members for equality. For objects of classObject
,eql?
is synonymous with==
. Subclasses normally continue this tradition by aliasingeql?
to their overridden==
method, but there are exceptions.Numeric
types, for example, perform type conversion across==
, but not acrosseql?
, so:1 == 1.0 #=> true 1.eql? 1.0 #=> false
So you're free to override this for your own uses, or you can override ==
and use alias :eql? :==
so the two methods behave the same way.
equal?
— identity comparisonUnlike
==
, theequal?
method should never be overridden by subclasses: it is used to determine object identity (that is,a.equal?(b)
iffa
is the same object asb
).
This is effectively pointer comparison.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With