Ruby + = перегрузка - PullRequest
       7

Ruby + = перегрузка

3 голосов
/ 04 декабря 2010

Что с этим не так?

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

Я не смог найти много онлайн.Кто-то сказал, что это потому, что + = в ruby ​​закончили вызывать +, а потом =, он пошутил, верно?

В забавном случае он был прав, есть ли какой-то обходной путь (помимо определения метода, называемого "add")?

Ответы [ 2 ]

6 голосов
/ 04 декабря 2010

Кто-то сказал, что это потому, что + = в ruby ​​завершил вызов +, а затем =, он пошутил, верно?

Нет, он прав (за исключением того, что "call =" немного неточно, поскольку = не является методом).

есть ли какое-то решение (кроме определения метода, называемого "add")?

Вы имеете в виду, кроме определения + и жить с фактом, что += изменит переменную, а не объект?

Вы можете изменить + для мутирования объекта, а затем вернуть self, в этом случае v1 += v2 будет таким же, как v1 + v2 и будет мутировать объект. Тем не менее, я настоятельно рекомендую против этого, поскольку никто не ожидает, что + будет мутировать (аналогично, большинство людей, владеющих рубинами, ожидают, что += переназначит переменную и не изменяет объект, поэтому попытки изменить это могут быть просто нежелательны в целом).

Кроме этого, нет, нет способа обойти это.

4 голосов
/ 04 декабря 2010

Он был прав.+= - это своего рода языковая конструкция, которая устанавливает ссылку на переменную равной результату подразумеваемой операции +.+= никогда не может быть методом и вести себя так, как ожидается:

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 и b здесь содержат ссылки на один и тот же объект, поэтому при запуске << для добавления элементана b также влияет a.Однако, как мы видим, += не должен изменять сам объект;он должен изменить то, что хранится в этой переменной, поэтому значение a здесь не трогается.

Это действительно в точности эквивалентно от руки.

b = a + [5, 6, 7]

Написано, чтоКстати, вы ожидаете, что новый массив будет сформирован, и a останется прежним.+= является сокращением именно для этого, поэтому не изменяет a.

Вы всегда можете определить свой собственный + для возврата нового вектора.

def +(v)
  new_vector = self.class.new
  new_vector.x = @x + v.x
  new_vector.y = @y + v.y
  new_vector
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...