Ruby的attr_accessor是否自动为属性创建实例变量?

One*_*ero 15 ruby

例如,如果我们写

class MyClass
  attr_accessor :something
end
Run Code Online (Sandbox Code Playgroud)

但没有使用实例变量显式创建初始化方法@something,Ruby会自动创建它吗?

mea*_*gar 30

否.实例变量在分配给它们之前不会定义,attr_accessor也不会自动执行.

尝试访问未定义的实例变量会返回nil,但不会定义该变量.在你写信之前,它们实际上并没有被定义.attr_accessor依赖于这种行为,除了定义一个getter/setter之外什么都不做.

您可以通过以下方式验证.instance_variables:

class Test
  attr_accessor :something
end
Run Code Online (Sandbox Code Playgroud)

x没有实例变量的新实例:

x = Test.new # => #<Test:0xb775314c>
x.instance_variables # => []
Run Code Online (Sandbox Code Playgroud)

调用getter不会导致@something定义:

x.something # => nil
x.instance_variables # => []
Run Code Online (Sandbox Code Playgroud)

调用setter 导致@something定义:

x.something = 3 # => 3
x.instance_variables # => ["@something"]
Run Code Online (Sandbox Code Playgroud)

设置somethingnil不会导致instance_variables恢复,因此我们可以确定返回的第一个空数组不仅仅是instance_variables省略nil值的情况:

x.something = nil # => nil
x.instance_variables # => ["@something"]
Run Code Online (Sandbox Code Playgroud)

您还可以验证这不仅仅是针对attr_accessor以下行为:

class Test
  def my_method

    @x # nil

    instance_variables # []

    @x = 3 

    instance_variables # ["@x"]
  end 
end

Test.new.my_method
Run Code Online (Sandbox Code Playgroud)