Ruby运行时错误冻结Fixnum

时间:2014-02-07 16:15:31

标签: ruby runtime-error

使用Ruby 2.0时出现以下错误,我不知道如何修复它。

class Numeric
  @@currencies = {'yen' => 0.013, 'euro' => 1.292, 'rupee' => 0.019, 'dollar' => 1}
  def method_missing(method_id)
    singular_currency = method_id.to_s.gsub( /s$/, '')
    @src_currency = singular_currency
    if @@currencies.has_key?(singular_currency)
      self * @@currencies[singular_currency]
    else
      super
    end
  end

  def in(dst_currency)
    (1 / @@currencies[dst_currency.to_s.gsub( /s$/, '')]) * self
  end
end

p 5.dollars.in(:euros)
p 10.euros.in(:rupees)

这会引发错误:

`method_missing': can't modify frozen Fixnum (RuntimeError)

我环顾四周,我明白这里发生了什么,但我不知道如何解决它。

2 个答案:

答案 0 :(得分:2)

这是错误的简化示例:

class Numeric
  def add_an_instance_variable
    @foo = 1
  end
end

 5.add_an_instance_variable

这是因为Fixnum被冻结,您不能修改它们。

原因是Fixnums are special

  

Fixnum对象具有立即值。这意味着他们什么时候   作为参数分配或传递,实际对象被传递   而不是对该对象的引用。

     

分配不会为Fixnum对象添加别名。实际上只有   一个Fixnum对象实例,用于任何给定的整数值,因此,for   例如,您不能将单例方法添加到Fixnum。任何企图   将单例方法添加到Fixnum对象将引发TypeError。

立即对象在Programming Ruby Book

中有详细说明

当你希望你的数字存储它们所在的货币时,你需要将它们包装在自己的类中。

(不要重新发明Money Gem。这很好。你可以使用它。)

答案 1 :(得分:0)

问题在于行@src_currency = singular_currency。摆脱“@”,你应该好好去。

msg告诉你的错误是你正在尝试修改冻结的Fixnum(通过为其分配一个实例变量)