The fact that TypeOfClass === TypeOfClass
is false
strikes me as counter-intuitive. In the following code, even if field.class
is the same class, it evaluates to false
:
case field.class
when Fixnum, Float
field + other_field
when Date, DateTime, Time
field
else
puts 'WAT?'
end
I did this:
Fixnum === Fixnum # => false
Class === Class # => true
I found another thread:
Integer === 3 # => true
Fixnum === 3 # => true
3.class # => Fixnum
I fail to find a reason for this language design. What were the language designers thinking when they baked in this behavior?
I think this is relevant to the answer provided in another thread. It is not unnatural to assume that Numeric === Integer
since an Integer
is a more specific type of Numeric
. But, it isn't:
Numeric === Integer #=> false
I think case
statements or ===
requires caution. If this operator is what we think it is , then, a Numeric
should be a Numeric
, an Integer
should be a Numeric
, etc.
Does anyone have an explanation of why this feature doesn't extend to classes? It seems like it would be easy enough to return true
if the compared class is a member of the class' ancestors.
Based on an answer submitted below, the code was originally classifying Time
(as extended by ActiveSupport:CoreExtensions::Integer::Time
and ActiveSupport:CoreExtensions::Float::Time
):
Timeframe = Struct.new(:from, :to) do
def end_date
case self.to
when Fixnum, Float
self.from + self.to
when Date, DateTime, Time
self.to
else
raise('InvalidType')
end
end
end
and in the console, I get:
tf = Timeframe.new(Time.now, 5.months)
# => #<struct Timeframe from=Tue Dec 10 11:34:34 -0500 2013, to=5 months>
tf.end_date
# => RuntimeError: InvalidType
# from timeframe.rb:89:in `end_date'
That's
Module#===
and its intended behavior:It simply returns
obj.kind_of? mod
:3
is both, anInteger
and aFixnum
because of its class hierarchy:Numeric
is not anInteger
, it's aClass
:But
3
,(2/3)
and1.23
are allNumeric
:Bottom line: for
case
statements, just usecase obj
instead ofcase obj.class
.Update
You are getting this error because
5.months
doesn't return anInteger
, but aActiveSupport::Duration
:Calling your method with
5.months.to_i
or addingActiveSupport::Duration
to your classes should fix it.