It all started with Nick asking a question like this in Singapore Ruby Brigade. How come?

String === String
=> false
# but
String == String
=> true

Let’s start with the easy one first:

Equality (==, eql?, equal?)

#== is the common equality method that compares object values, ignoring the object id. #eql? is the alias of #==, so they are the same. Btw the “#” prefix means it is an instance method (just in case), without the prefix, it means a class method.

The stricter version of is #equal? compares the object id. Example:

"test" == "test"         
# returns true, both have the same value, i.e. "test"

"test".equal?("test")  
# returns false, because "test" (left) is a different object from "test" (right), where "test".__id__ != "test".__id__

Case Equality (===)

=== is the case equality method, in English it means it is called internally when you use ‘case’ statement, but of course, it can also be called outside the case statement.

=== method functions differently, depending on the caller class type.

If you call it on a Class, it will check if the compared object is an instance/descendant of the class. On Object, it is the same with #== method. Please refer to Ruby documentation for more information on how it performs on different class types.

String === "test"    
# returns true because "test" is an instance of String

"test" === "test"
# returns true, because both objects have the same value or "==" returns true

"test" === "different test"
# returns false, because the two objects have different values.

Just a bit more spice, on Ruby on Rails (RoR) framework, the Range class overrides “===” method to returns true if the compared value is found in the in the range values.

1..10 === 1    # returns true
1..10 === 11   # returns false

case var
   when 1..10
       "do some stuff here"
   when 11..20
       "do something else here"
   else
       "out of range"
end

So back to the one-million-dollar question, why then String === String returns false?

Calling String in the runtime environment, returns a Class object that represents String class type. If you call String.__id__, it will return the object id of Class object. Thus:

String === String
# returns false, because String (right) is treated as a Class object, passed as an argument to String  "===" method.

And… I think you get it, obviously Class object is not an instance of String class. Sweet.

And why String == String returns true?

You should be able to answer it by now. =)

2 Comments . Comments Feed . Trackback URI
Mon, 9 Oct 06 11:51 pm . choonkeat wrote:

very clear :-) thanks. btw, u haf a typo

irb(main):001:0> String == “test”
=> false

Tue, 10 Oct 06 08:32 am . Herryanto Siatono wrote:

Okay, got that. Thanks!

Add Your Comment



(optional)