在什么情况下我应该使用实例变量而不是其他变量类型?

use*_*052 6 ruby variables ruby-on-rails class ruby-on-rails-3

我正在使用Ruby on Rails 3,我想知道在什么情况下我应该使用实例变量而不是其他变量类型,如果有安全原因那些.

例:

# Using an instance variable
@accounts = Account.find(...)

# Using a "local"\"normal" variable
account = Account.find(...)
Run Code Online (Sandbox Code Playgroud)

Pan*_*kos 10

通常,实例变量是本地的并且持久存储在对象的实例中,而局部变量只是本地变量并且持久存储在函数/对象/块范围内.例如:

class User
  def name
    @name
  end

  def name= name
    @name = name
  end
end

def greet user
  name = user.name || 'John'
  p "Hi, my name is #{name}"
end

user = User.new
greet user
=> 'Hi, my name is John'
name
=> NameError: undefined local variable or method 'name' for main:Object
user.name = "Mike"
greet user
=> 'Hi, my name is Mike'
@name
=> nil
Run Code Online (Sandbox Code Playgroud)

在greet函数中name是一个仅在该函数中定义的局部变量.name变量在函数的第一行设置name = user.name || 'John',但其值不会在函数外部持久化.当你尝试调用时,name你会得到一个NameError因为name只被定义为greet函数中的局部变量.

@name是User类的用户实例的本地.当您尝试在该上下文之外调用它时,您会得到nil.这是本地变量和实例变量之间的一个区别,如果尚未定义实例变量,则返回nil,而本地非实例变量会引发Error.

请注意,两个变量类型都是特定上下文的本地变量.@name在用户实例中定义,因此当您调用时,user.name您正在调用用户实例中的名称函数,其中@name定义了该函数.name仅在greet函数中定义,因此当您调用时,p "Hi, my name is #{name}"您可以获取值,name因为您在其定义范围内.

  • 你能解释为什么在getter方法中使用@name而不是简单的局部变量名吗?由于实例变量和局部变量在其上下文中都是有效的,为什么要区分这两者? (2认同)

Dav*_*vy8 10

@Pan的回答很好地解释了它们之间的区别.

通常(几乎任何语言)您都希望在所需的最小范围内定义变量.因此,如果您不需要在函数调用之间保留某些内容,请将其设置为本地.

如果需要跨函数调用持久化变量,但仅针对特定类实例,请将其设为实例变量.

如果你需要在该类的每个实例之间共享的东西,那么使用类变量,但是对此的需求应该有点罕见,所以仔细考虑你是否真的需要一个类变量.

(免责声明:我只使用Ruby大约2周,所以这主要是语言无关的答案,但我很确定它适用于Ruby.如果我错了,请随意纠正我.)