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