3

可能重复:
在 Ruby 中有没有办法重载初始化构造函数?

BigDecimal不像初始值那样采用浮点数,所以我正在编写一个构造函数来处理它。它似乎忽略了初始化方法并调用了默认构造函数。

它抛出TypeError can't convert Float into String (TypeError)

该方法format确实有效。

文件 BigDecimal.rb:

require 'bigdecimal'

class BigDecimal

    def initialize
        if self.class == Float
            super self.to_s
        end
    end

    def format
        sprintf("%.2f", self)
    end

end

然后,在文件 test.rb 中:

require 'BigDecimal' # => true
bd = BigDecimal.new('54.4477') # works
puts bd.format # 54.44
bd2 = BigDecimal.new(34.343) # TypeError: can't convert Float into String (TypeError)

红宝石 1.9.2

4

2 回答 2

7

您的代码存在问题:

  1. 您使用猴子补丁而不是继承,因此在您的initialize方法中,super将调用的初始化方法Object,它是 BigDecimal 的超类。要调用默认构造函数,您必须使用其他方法,如下所示。

  2. 您没有为该initialize方法输入参数。

  3. BigDecimal 将浮点数作为构造函数参数

所以,

  1. 您可以直接使用默认构造函数并将浮点数传递为:

    BigDecimal.new(34.343, 5) # 5 is the precision
    
  2. 您可以通过这种方式覆盖构造函数:

注意:我们通常使用别名initialize方法。但是在这种情况下,这似乎不起作用(由于某些未知原因,initialize不会被调用)......所以我们必须给new更基本的方法起别名。

    require 'bigdecimal'

    class BigDecimal

        class << self
          alias_method :__new__, :new  #alias the original constructor so we can call later
          def new(*args)
              if args.length == 1 && args[0].is_a?(Float)
                  __new__(args[0].to_s)
              else
                  __new__(*args)
              end
          end
        end

        def format
            sprintf("%.2f", self)
        end

    end

    BigDecimal.new(12.334)
    #<BigDecimal:10a9a48,'0.12334E2',18(18)>
于 2012-06-21T17:03:04.620 回答
5

BigDecimal 不像初始值那样采用浮点数

你确定吗?

BigDecimal.new(2.4)
#=>ArgumentError: can't omit precision for a Rational.

所以你必须给出一个精度作为第二个参数:

BigDecimal.new(2.4, 2)
#=> #<BigDecimal:7ff689b0f2e8,'0.24E1',18(36)>

文档没有指出 1.9.2 和 1.9.3 之间的变化。

于 2012-06-21T15:58:37.897 回答