В Ruby, если мы определяем вызов метода "c =", почему он не может быть вызван c = 3? - PullRequest
5 голосов
/ 25 февраля 2011

Например, если мы

def c=(foo)
  p "hello"
end

c = 3
c=(3)

и "привет" не будет напечатан. Я знаю, что это может быть вызвано self.c = 3 но почему? и каким образом это может быть вызвано?

Ответы [ 3 ]

8 голосов
/ 25 февраля 2011

c = 3c = (3), что ему полностью соответствует) всегда интерпретируется как присвоение локальной переменной. Вы могли бы сказать, что его следует интерпретировать как присвоение локальной переменной, только если метод c= не определен для себя, но есть различные проблемы с этим:

  1. Как минимум, МРТ должно знать во время анализа, какие локальные переменные определены в данной области. Однако во время разбора неизвестно, определен данный метод или нет. Таким образом, ruby ​​не может знать, определяет ли c = 3 переменную c или вызывает метод c= до времени выполнения, что означает, что он не будет знать, определена ли локальная переменная c во время анализа. Это означает, что MRI потребуется изменить способ обработки локальных переменных в синтаксическом анализаторе, чтобы он работал так, как вы этого хотите.

  2. Невозможно определить локальную переменную с именем c, если метод c= уже определен. Вы можете сказать, что все в порядке, потому что локальные переменные и методы с одинаковыми именами в любом случае сбивают с толку. Однако рассмотрим случай, когда вы определяете method_missing, так что foo= определяется для каждого возможного foo (как, например, для OpenStruct s). В этом случае было бы невозможно определить локальные переменные вообще.

  3. Вы не можете точно сказать, реагирует ли объект на c= без его запуска, потому что он может быть обработан method_missing. Так что все это на самом деле было бы неразрешимо.

7 голосов
/ 25 февраля 2011

Поскольку локальные переменные имеют приоритет над ранее определенными методами / переменными с тем же именем.В этом случае вам необходимо указать «self», чтобы c не интерпретировалось как объявление / присвоение локальной переменной.

3 голосов
/ 25 февраля 2011

Ruby вызывает этот метод только в том случае, если код не может быть интерпретирован как присвоение переменной. Нет лучшего способа форсировать вызов метода.

self.c = 1
send(:c=, 1)
__send__(:c=, 1)
method(:c=).call(1)
method(:c=)[1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...