Search code examples
rubystringbooleanequality

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.


Solution

  • === 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.