为什么string + fixnum add会产生强制错误?

时间:2009-10-12 06:01:57

标签: ruby

为什么红宝石添加不能强制给定字符串到fixnum,反之亦然?

irb>fixnum = 1
=> 1
irb> fixnum.class
=> Fixnum
irb> string = "3"
=> "3"
irb> string.class
=> String
irb> string.to_i
=> 3
irb> fixnum + string
TypeError: String can't be coerced into Fixnum
    from (irb):96:in `+'
    from (irb):96
    from :0
irb(main):097:0> 

4 个答案:

答案 0 :(得分:10)

因为ruby不知道您是要将字符串转换为int还是将int转换为字符串。在例如java 1 + "3""13"。 Ruby更喜欢引发错误,以便用户可以决定是to_s一个操作数还是to_i另一个操作数,而不是自动做错事。

答案 1 :(得分:5)

它吐出错误,因为红宝石不知道你想要什么。 String + fixnum是一个含糊不清的语句。它可能意味着您要添加字符串的int值和数字,或者int和字符串的字符串值。例如:

str = "5"
num =  3

puts str.to_i + num
=> 8

puts str + num.to_s
=> 53

而不是猜测你想要哪一个,ruby只是抛出异常。

答案 2 :(得分:1)

您需要将变量设置回自身,因为执行.to_i会返回一个整数值,但不会修改原始对象。

>> string = "3"
=> "3"
>> string.class
=> String
>> string.to_i
=> 3
>> string
=> "3"
>> string.class
=> String
>> string = string.to_i
=> 3
>> string.class
=> Fixnum

答案 3 :(得分:1)

Fixnum#+只是一种方法。简化它的工作原理如下:

class Fixnum
  def +(other)
    if Fixnum === other
      # normal operation
    else
      n1, n2= other.coerce(self)
      return n1+n2
    end
  end
end

coerce用于自动数字类型转换。例如,如果您执行42 + 3.141,则会使用此选项。 ruby中的字符串不能自动转换为数值。您可以增强String类以便能够执行此操作。你只需要做

class String
  def coerce(other)
    coerced= case other
    when Integer
      self.to_i
    when
      self.to_f
    end
    return coerced, other
  end
end

现在你可以做到

23 + "42" # => 65
0.859 - "4" # => 3.141

这不是另一种方式。 coerce仅适用于数字值"23" + 42不起作用。 String#+不会使用强制。

简化+已在Fixnum中完成,而不是故意在Integer中完成。 FixnumBignum有各自不同的方法,因为它们在内部的工作方式非常不同。