Рациональные - оригинальные числа в рубине
Как я могу получить оригинальные номера? Например, когда я печатаю:
r = Rational(2, 10)
# (1/5)
2 и 10 будут изменены на 1 и 5:
r.numerator # 1
r.denominator # 5
Как получить 2 и 10 из экземпляра класса Rational (r
)?
Я пропатчил Rational класс и создал новый метод (Rational_o
):
def Rational_o *args
x, y = args
r = Rational *args
r.x = x
r.y = y
r
end
class Rational
attr_accessor :x, :y
end
Это работает, но есть ли встроенный метод или переменная (и), где хранятся оригинальные x & y?
3 ответа
Нет, нет Сокращение является основным и распространенным способом нормализации рациональных чисел. Зачем рациональному числу сохранять исходный числитель и знаменатель? Это не имеет смысла.
Ваш вопрос похож на вопрос "Есть ли строка, созданная "foo" + "bar"
(который становится "foobar"
) сохранить оригинальные подстроки "foo"
а также "bar"
? Где они хранятся?
Если вы действительно хотите сохранить исходные числа, то рациональное число - это не то, что вам нужно, а подклассы Rational
это не правильный путь. Вы должны использовать массив, содержащий пару чисел.
Рациональные числа нормализуются при инициализации, поэтому вы не можете знать, какие числа были заданы в качестве исходных аргументов. Вы также не можете подкласс Rational
установить собственный инициализатор, и использование обезьяньих патчей в действительности не является оптимальным способом достижения того, чего вы хотите достичь (что, я думаю, вы знаете).
Что вы можете сделать, это создать прокси вокруг Rational
с BasicObject
который сохраняет исходные аргументы и не будет мешать нормальной работе оригинала Rational
учебный класс
class RationalWithArgumentStore < BasicObject
attr_accessor :original_arguments, :rational
def initialize *args
@original_arguments = args
@rational = Rational *args
end
# Basic Object is a basic object, but defines ==
# so let's overwrite it to route to rational
def == other
@rational == other
end
# Route all unknown method calls to rational
def method_missing meth, *args, &block
@rational.send meth, *args, &block
end
end
def RationalWithArgumentStore(*args)
RationalWithArgumentStore.new(*args)
end
Так что теперь вы можете сделать
my_rational = RationalWithArgumentStore(2,10)
my_rational.original_arguments #=> [2, 10]
#use it like a normal rational
my_rational * 3
my_rational.truncate
Нет, нет такого встроенного частного или публичного метода, который бы делал то, что вы хотите.
Если вы действительно хотите сохранить исходные числа внутри метода экземпляра, ваш обезьян-патч, безусловно, является одним из способов сделать это.
На самом деле, метод Rational(a,b)
это метод экземпляра, определенный вне класса Rational
, вроде как Array()
а также String()
методы.