tags:

views:

176

answers:

3

I've seen how to overload + and * in Ruby, so that my_obj + other calls my_obj.+(other). In Python, you do this with __add__, and there's a corresponding __radd__ for overloading other + my_obj. Is there really no equivalent right-sided addition/multiplication in Ruby, and does that make it necessary to redefine + for each potential class of other?

In brief: say I have an object X which belongs to some new class defined by me. It's easy to write code for X + 5, but it seems that in order to handle 5 + X I'd need to redefine Fixnum.+. Is this true?

A: 

Yes. If you want to alter the behavior on 5 + x, you have to redefine + on whatever 5 is, since you're in fact calling 5.+(x) because of Ruby treating these kinds of operations as mechod calls.

August Lilleaas
+5  A: 

No, you don't need to redefine Fixnum#+ (or any other arithmetic method of ruby's numeric classes). The arithmetic methods of the numeric classes will call coerce if the two operands are not the same class. So if you define a coerce method for your class, 5 + instance_of_your_class will work fine without any changes to Fixnum#+.

Edit: Here's an example of using coerce:

class MyNum
  attr_accessor :num

  def initialize(num)
    @num = num
  end

  def +(o)
    lhs, rhs = coerce(o)
    MyNum.new(lhs.num + rhs.num)
  end

  def coerce(o)
    if o.is_a? MyNum
      [self, o]
    else
      [self, MyNum.new(o)]
    end
  end
end

MyNum.new(5)+3 #=> #<MyNum:0x87fca08 @num=8>
3+MyNum.new(5) #=> #<MyNum:0x8807980 @num=8>
sepp2k
great, this is perfect, thanks!
Peter
A: 

The RHS is coerced and needs to implement the to_i method which needs to return an appropriate value. The Numeric's classes implementation of to_int will end up calling it as part of the process of addition where other classes are involved on the RHS than strict Numeric descendants.

Paul Keeble