Почему принуждение не срабатывает, когда я использую "" * Point - PullRequest
0 голосов
/ 13 мая 2019

Я пытаюсь выяснить метод coerce. когда я определил метод * и метод coerce. integer * Point срабатывает coerce, но "" * Point не срабатывает. Почему?

Ошибка:

coerce.rb:34:in `*': no implicit conversion of Point into Integer (TypeError)   from coerce.rb:34:in `<main>'

Код:

class Point
  def initialize x,y
    @x,@y = x,y
  end

  def * x
    p "* called" 
    @x *= x
    @y *= x
  end

  def coerce other
    p 'coerce called'

    if other.is_a? String
      p "converted"
      [self, other.to_i]
    else
      [self,other]
    end
    #[3,other]
  end
end

p1= Point.new 1,1
p1*2
p p1
2*p1
p p1

p p1.coerce(2)

p "string test====="
"2" * p1

Выход:

"* called"
#<Point:0x00564f5de89dd0 @x=2, @y=2>
"coerce called"
"* called"
#<Point:0x00564f5de89dd0 @x=4, @y=4>
"coerce called"
[#<Point:0x00564f5de89dd0 @x=4, @y=4>, 2]
"string test====="
coerce.rb:34:in `*': no implicit conversion of Point into Integer (TypeError)
    from coerce.rb:34:in `<main>'

Кто подскажет, почему и как заставить "2" * p1 работать?

1 Ответ

2 голосов
/ 13 мая 2019

Загвоздка в том, что хотя Ruby позволяет вам переопределять операторы для этого, они очень точны в отношении порядка.

Помните, что этот код:

point * 2

В конце концов Ruby понимается как:

point.send(:*, 2)

Какой метод вы определили для этого конкретного случая, Point#*.

Пока этот код:

2 * point

В итоге понимается как:

2.send(:*, point)

Где это идет к Integer#*, и вы не можете это контролировать. Хотя вы можете это исправить, это выглядит как необычайно плохая идея. Лучше всего документировать, как работает ваша система, и показать примеры правильного порядка.

В Ruby левое значение в бинарном операторе в основном вызывает выстрелы, правое значение - просто пассажир.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...