如何在Ruby中重载构造函数?

时间:2012-06-21 15:53:09

标签: ruby constructor overloading ruby-1.9.2 method-overriding

  

可能重复:
  In Ruby is there a way to overload the initialize constructor?

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

抛出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)

Ruby 1.9.2

2 个答案:

答案 0 :(得分:7)

代码问题:

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

  2. 您没有为initialize方法添加参数。

  3. BigDecimal将float作为构造函数参数

  4. 因此,

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

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

    3. 注意:我们通常使用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)>
      

答案 1 :(得分: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之间的变化。