Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does "foo".class === String return false?

I became curious when this didn't work as I expected:

var = "foo"
case var.class
when String
  puts "bar"
else
  puts "baz"
=> "baz"

I understand that the case statement is using ===, but I don't understand what === does. The docs say...

Case Equality – For class Object, effectively the same as calling #==, but typically overridden by descendants to provide meaningful semantics in case statements.

http://ruby-doc.org/core-2.2.3/Object.html#method-i-3D-3D-3D

Does this mean that === in Class (or one of its modules) overrides === in Object? I'm confused.

like image 856
eeeeeean Avatar asked Feb 08 '23 10:02

eeeeeean


2 Answers

=== is overridden for Class objects (and more generally, Module objects) to mean "is the right-hand side an instance of the left-hand side".

For instance:

>> String === ""
=> true
>> Class === String
=> true

This is unintuitive, but it's true. It does, however, make what you're trying to do even shorter:

var = "foo"
case var
when String
  puts "bar"
else
  puts "baz"
end
# outputs "bar", since String === "foo"

Here's why your attempt didn't work: Ruby evaluates String === String, which is false, since the String class is not itself a string.

like image 93
Jeremy Roman Avatar answered Feb 23 '23 16:02

Jeremy Roman


You are dealing with case equality here. Here, it is overridden by descendants to provide meaningful semantics. In this case, Module overrides it.

Case Equality — Returns true if an object is an instance of a module or one of the module's descendants. Of limited use for modules, but can be used in case statements to classify objects by class.

In modules, === acts like Ruby's is_a? method.

In your case, it returns false because "Foo".class isn't an instance of the string class.

"Foo".class.is_a?(String)
=> false
like image 21
Richard Hamilton Avatar answered Feb 23 '23 15:02

Richard Hamilton