使用`===`(包含运算符)比较类

odd*_*zen 1 ruby types class switch-statement comparison-operators

这事实上TypeOfClass === TypeOfClass是false给我的印象是反直觉.在以下代码中,即使field.class是同一个类,它的计算结果为false:

case field.class
when Fixnum, Float
  field + other_field
when Date, DateTime, Time
  field
else
  puts 'WAT?'
end
Run Code Online (Sandbox Code Playgroud)

我这样做了:

Fixnum === Fixnum # => false
Class === Class   # => true
Run Code Online (Sandbox Code Playgroud)

我发现另一个线程:

Integer === 3 # => true
Fixnum === 3  # => true
3.class       # => Fixnum
Run Code Online (Sandbox Code Playgroud)

我找不到这种语言设计的原因.语言设计师在这种行为中思考的是什么?

我认为这与另一个帖子中提供的答案有关.假设Numeric === Integera Integer是一种更具体的类型,这并不是不自然的Numeric.但是,它不是:

Numeric === Integer #=> false
Run Code Online (Sandbox Code Playgroud)

我认为case陈述或===要求谨慎.如果这个运算符是我们认为的那样 那么,a Numeric应该是a Numeric,a Integer应该是a Numeric等等.

有没有人解释为什么这个功能不扩展到类?true如果比较的类是类的祖先的成员,似乎很容易返回.

根据下面提交的答案,代码最初是分类Time(由ActiveSupport:CoreExtensions::Integer::Time和扩展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
Run Code Online (Sandbox Code Playgroud)

在控制台中,我得到:

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'
Run Code Online (Sandbox Code Playgroud)

hir*_*lau 5

我真的没有看到这里的问题.对于类,大小写相等运算符会询问左手参数是否是类(或任何子类)的实例.所以Fixnum === Fixnum真的问:"Fixnum类本身是Fixnum的子类吗?" 不它不是.

班级Class本身是一类吗?Class === Class, 是的.

操作员的观点是你不应该去找班级.在没有.class方法的情况下使用case语句有什么问题?

case field
when Fixnum, Float
  field + other_field
when Date, DateTime, Time
  field
else
  puts 'WAT?'
end
Run Code Online (Sandbox Code Playgroud)

如果你有一个更复杂的例子,你可以编写自己的lambda来简化case语句:

field_is_number =  -> x {[Fixnum, Float].include? x.class}
field_is_time   =  -> x {[Date, DateTime, Time].include? x.class}

case field.class
  when field_is_number
    field + other_field
  when field_is_time
    field
  else
    puts 'WAT?'
end
Run Code Online (Sandbox Code Playgroud)