Рациональные - оригинальные числа в рубине

Как я могу получить оригинальные номера? Например, когда я печатаю:

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() методы.

Другие вопросы по тегам