Есть три проблемы с вашим кодом:
Вы создаете новый класс EanControl::Fixnum
, но вы на самом деле хотите изменить существующего встроенного ::Fixnum
, Решение: явно начать постоянный поиск с верхнего уровня, или, более идиоматически, просто отбросить модуль.
module EanControl
class ::Fixnum
# …
end
end
# although it would be much simpler to just do this:
class Fixnum
# …
end
Вы определяете roundup
как одноплодные методы объекта Fixnum
, но вы называете его как метод экземпляра экземпляров Fixnum
. Решение: сделать roundup
метод экземпляра:
class Fixnum
def roundup
return self if (self % 10).zero? # already a factor of 10
self + 10 - (self % 10) # go to nearest factor 10
end
end
Спецификация Рубин Язык фактически не гарантирует, что даже являетсяFixnum
класса. Это только гарантирует, что существует класс Integer
, и это позволяет использовать различные реализации для подклассов, специфичных для реализации. (Например, YARV имеет Fixnum
и Bignum
подклассы Integer
.) Поскольку вы добавляете только метод к Fixnum
, он не будет работать для других Integer
s, которые не являются Fixnum
s. А поскольку диапазон Fixnum
s отличается для разных реализаций архитектур (например, на YARV на 32-битных системах, Fixnum
s - 31 бит, на 64-битных системах - 63 бит, на JRuby они всегда 64 бит), вы даже не знаю точно, на каких числах ваш метод будет работать, и когда он потерпит неудачу. (Например: 9223372036854775808.roundup # NoMethodError: undefined method 'roundup' for 9223372036854775808:Bignum
.) Решение: сделать метод метод экземпляра Integer
:
class Integer
def roundup
return self if (self % 10).zero? # already a factor of 10
self + 10 - (self % 10) # go to nearest factor 10
end
end
Наконец, я хочу предложить, по крайней мере, используя подмешать здесь:
module IntegerWithRoundup
def roundup
return self if (self % 10).zero? # already a factor of 10
self + 10 - (self % 10) # go to nearest factor 10
end
end
class Integer
include IntegerWithRoundup
end
Теперь, если кто-то отлаживает код и чудеса, где этот метод roundup
приходит, есть четкий след в родословной цепи:
12.method(:roundup).owner
# => IntegerWithRoundup
Еще лучше было бы использовать утонченность, что путь ваш monkeypatch не загрязнять глобальное пространство имен:
module IntegerWithRoundup
module Roundup
def roundup
return self if (self % 10).zero? # already a factor of 10
self + 10 - (self % 10) # go to nearest factor 10
end
end
refine Integer do
include Roundup
end
end
12.roundup
# NoMethodError: undefined method `roundup' for 12:Fixnum
using IntegerWithRoundup
12.roundup
# => 20
Благодарим вас за фантастический андерсер. – narzero