Почему Ruby не позволяет устанавливать локальную переменную, используя выражение, содержащее программу чтения полей с тем же именем, что и у локальной переменной? - PullRequest
0 голосов
/ 14 ноября 2018

Рассмотрим следующий код.

class A
  attr_reader :n

  def initialize
    @n = 1
  end

  def set_local_n
    n = 10
  end

  def using_field_reader_locally
    n + 100
  end

  def using_field_reader_to_set_local_x
    x = n + 1000
  end

  def using_field_reader_to_set_local_n
    n = n + 1000  # This line raises a NoMethodError. Why?
  end
end

Почему закомментированная строка выдает ошибку? Почему Ruby не позволяет устанавливать локальную переменную, в данном случае n, используя выражение, содержащее средство чтения полей с тем же именем, что и локальная переменная? Почему все другие методы экземпляра выполняются без проблем, но using_field_reader_to_set_local_n выдает ошибку.

Обратите внимание, что я НЕ собираюсь определять n локально в using_field_reader_to_set_local_n с выражением, включающим локально определенный n в set_local_n. Я намерен определить n локально в using_field_reader_to_set_local_n с выражением, включающим полевого считывателя @n. Определение set_local_n предназначено для демонстрации того, что n может быть определен локально, пока существует считыватель полей с именем n.

1 Ответ

0 голосов
/ 14 ноября 2018

Если вы посмотрите внимательно, NoMethodError не о том, что нет метода n, а о методе + для NilClass.

В этом утверждении:

n = n + 1000

Руби должна решить, что такое n. Поскольку вы назначаете что-то этому (n =), это не метод. Если вы хотите вызвать метод n=, вам нужно было указать явный получатель (self.n =).

Так что это должна быть переменная. В данном случае локальная переменная.


Теперь, чтобы понять что-то вроде:

n = n

Руби заканчивает тем, что присваивает nil n. Это связано с тем, что внутренним компонентам нужно поместить заполнитель для имени переменной, которая присваивается.


Итак, когда вы делаете:

n = n + 1000

Что происходит:

  1. Создать новую локальную переменную n со значением заполнителя (nil).
  2. Попытка присвоить ему все, что находится справа.
  3. Посчитайте, что справа - nil + 1000.
  4. nil не имеет + метода, поэтому возникает ошибка.

Чтобы сделать то, что вы хотели, вы должны явно указать переменную экземпляра для ее значения:

n = @n + 1000

Или явно вызвать считыватель атрибутов:

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