开发者

Ruby += overloading

What is wrong with this?

class Vec2
  attr_accessor :x, :y
  # ...
  def += (v)
    @x += v.x
    @y += v.y
    return self
  end
  # ...
end

I've not been able to find much online. Someone said it is because += in ru开发者_开发技巧by is done calling + and then =, he was kidding right?

In the amusing case he was right, is there some workaround (aside from defining a method called "add")?


Someone said it is because += in ruby is done calling + and then =, he was kidding right?

No, he is right (except that "calling =" is a bit inaccurate as = is not a method).

is there some workaround (aside from defining a method called "add")?

You mean other than defining + and living with the fact that += will change the variable and not the object?

You could change + to mutate the object and then return self, in which case v1 += v2 would be the same as v1 + v2 and would mutate the object. However I'd strongly advise against that as no one would expect + to be mutating (similarly most ruby-literate people would expect += to reassign the variable and not mutate the object, so trying to change that might just be inadvisable altogether).

Other than that, no, there's no way to work around this.


He was right. += is a language construct of sorts, that sets the variable reference equal to the result of the implied + operation. += can never actually be a method and behave as expected:

a = [1, 2, 3]
b = a
b << 4
b += [5, 6, 7]
p a # => [1, 2, 3, 4]
p b # => [1, 2, 3, 4, 5, 6, 7]

a and b here both contain references to the same object, which is why running << to add an element to b also affects a. As we can see, however, += isn't supposed to modify the object itself; it's supposed to change what's being stored in that variable, which is why the value of a is here untouched.

It really is exactly equivalent to the longhand.

b = a + [5, 6, 7]

Written that way, you expect a new array to be formed, and for a to remain the same. += is shorthand for exactly that, so does not mutate a in any way.

You can always define your own + to return a fresh vector.

def +(v)
  new_vector = self.class.new
  new_vector.x = @x + v.x
  new_vector.y = @y + v.y
  new_vector
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜