2

Можно создать дубликат:
In Ruby is there a way to overload the initialize constructor?Как перегрузить contructor в Ruby?

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) 

Руби 1.9.2

+0

http://stackoverflow.com/a/3958786/643500 –

+0

перенастройка конструктор с версией, которая не принимает никаких аргументов. Уверен, что вы тестируете код? Если да, это означает, что инициализация никогда не называется (в любом случае это багги). Вместо этого попробуйте подклассифицировать BigDecimal. Подкласс предпочтительнее по сравнению с monkeypatching большую часть времени. –

ответ

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)> 
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.

+0

BigDecimal.ver => "1.0.1". Какая версия у вас есть? –

+0

1.1.0. Но, как я уже сказал, документы 1.9.2 уже предлагают такое же поведение. –

+0

Интересно, если документы или неправильные или если есть проблема с моей установкой. Наверное, я просто перейду к 1.9.3. Благодарю. –

Смежные вопросы