Подтвердить что ты не робот

Создает ли Ruby attr_accessor автоматически переменные экземпляра для атрибутов?

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

class MyClass
  attr_accessor :something
end

но явно не создал метод инициализации с переменной экземпляра @something, Ruby автоматически создает его?

4b9b3361

Ответ 1

Нет. Переменные экземпляра не определены до тех пор, пока вы их не назначите, а attr_accessor не сделает это автоматически.

Попытка доступа к переменной экземпляра undefined возвращает nil, но не определяет эту переменную. Они фактически не определяются, пока вы не напишите им. attr_accessor полагается на это поведение и ничего не делает, кроме определения геттера/сеттера.

Вы можете проверить это, проверив .instance_variables:

class Test
  attr_accessor :something
end

Новый экземпляр x не имеет переменных экземпляра:

x = Test.new # => #<Test:0xb775314c>
x.instance_variables # => []

Вызов геттера не вызывает @something для определения:

x.something # => nil
x.instance_variables # => []

Вызов установщика приводит к тому, что @something станет определяемым:

x.something = 3 # => 3
x.instance_variables # => ["@something"]

Настройка something назад на nil не приводит к возврату instance_variables, поэтому мы можем быть уверены, что первый пустой возвращенный массив - это не просто случай instance_variables omitting nil values:

x.something = nil # => nil
x.instance_variables # => ["@something"]

Вы также можете проверить, что это не просто поведение, характерное для attr_accessor:

class Test
  def my_method

    @x # nil

    instance_variables # []

    @x = 3 

    instance_variables # ["@x"]
  end 
end

Test.new.my_method

Ответ 2

Сорт. В Ruby переменные экземпляра создаются, когда они сначала назначаются. Это полностью прозрачно для программиста. По умолчанию они равны нулю, пока не будут назначены.

Пример:

class Foo
  attr_accessor :bar
  def baz
    @nonexistant
  end
end
f.bar #=> nil
f.baz #=> nil
f.bar = 4
f.bar #=> 4

Пока вы не назначили значение переменной экземпляра, оно плавает в состоянии undefined nil.