I have been biten by this (and other) unexpected implicit #to_i
call(s) myself. OO-philospical issuses about the validity of adding a
RomanInteger class to the Numeric class hierachie aside, if you are
willing to beat the barbwires around extending the Integer class you
can construct such a RomanInteger class as a subclass of Integer.
(The script probably requires 1.7)
------------
class Integer
class << self
def new; "dummy for undef" end
def allocate; "dummy for undef" end
undef_method :new
undef_method :allocate
def new (*bla,&b) ; super (*bla,&b) end
def allocate; super end
end
end
class Fixnum
class << self
undef_method :new
undef_method :allocate
end
def to_rint; RomanInteger.new self end
end
class Bignum
class << self
undef_method :new
undef_method :allocate
end
end
class RomanInteger < Integer
Max=4999
def initialize a
raise ArgumentError unless a.kind_of?(Fixnum) and (0 < a) and (a
<= Max)
@rep = a
end
def <=>(other); @rep <=> other.rep end
def +(other)
if other.kind_of? Fixnum
return RomanInteger::new @rep + other
else
raise ArgumentError
end
end
def -(other)
if other.kind_of? RomanInteger
return @rep - other.rep
else
raise ArgumentError
end
end
def coerce(other);[self,other] end
def inspect
case @rep
when 1 then 'I'
when 2 then 'II'
when 3 then 'III'
when 4 then 'IV'
when 5 then 'V'
when 6 then 'VI'
else raise 'needs more work'
end
end
protected
attr_reader :rep
end
r1 = 1.to_rint
r10 = 10.to_rint
p (r6 = -4 + r10) # => VI
p (r5 = r1 + 4) # => V
p (r5 - r6) # => -1
(r1..r5).each do |r| p r end