How do I get the original numbers?
For example when I type:
r = Rational(2, 10)
# (1/5)
2 and 10 will be changed to 1 and 5:
r.numerator # 1
r.denominator # 5
How do I get 2 & 10 from instance of Rational class(r
)?
I monkey-patched Rational class and created new method(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
It works, but is there build-in method or variable(s) where original x & y are stored?
No, there isn't. Reduction is a basic and common way to normalize rational numbers. Why would a rational number keep the original numerator and denominator? It does not make sense.
Your question is like asking "Does a string created by "foo" + "bar"
(which becomes "foobar"
) keep the original substrings "foo"
and "bar"
? Where are they stored?"
If you really want to keep the original numbers, then a rational number is not what you want, and subclassing Rational
is not the right way to go. You should use an array holding a pair of numbers.
Rational numbers get normalized on initialization, so you can not know which numbers where given as original arguments. You can also not subclass Rational
to install an initializer of your own, and monkeypatching as you do is not really the optimal way to achieve what you want to achieve (which I think you know).
What you can do is create a proxy around Rational
with BasicObject
which preserves the original arguments and will not disturb normal operation of the original Rational
class
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
So now you can do
my_rational = RationalWithArgumentStore(2,10)
my_rational.original_arguments #=> [2, 10]
#use it like a normal rational
my_rational * 3
my_rational.truncate
No, there is no such inbuilt private or public method that does what you want to do.
If you really want to store the original numbers inside the instance method, your monkey-patch is definitely one of the ways to do so.
In fact, the method Rational(a,b)
is an instance method defined outside the class Rational
, kind of like Array()
and String()
methods.