При каких обстоятельствах я должен использовать переменные экземпляра вместо других типов переменных? - PullRequest
6 голосов
/ 12 марта 2011

Я использую Ruby on Rails 3, и я хотел бы знать, при каких обстоятельствах я должен использовать переменные экземпляра вместо других типов переменных и есть ли для них причины безопасности.

Пример:

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

# Using a "local"\"normal" variable
account = Account.find(...)

Ответы [ 2 ]

10 голосов
/ 12 марта 2011

@ Ответ Пэна дает хорошее объяснение разницы между ними.

В общем (практически на любом языке) вы хотите определить переменные в наименьшей требуемой области видимости.Поэтому, если вам не нужно что-то сохранять при вызове функций, сделайте это локальным.

Если вам нужно, чтобы переменная сохранялась при вызовах функций, но только для определенного экземпляра класса, сделайте ее переменной экземпляра.

Если вам нужно что-то, что совместно используется каждый экземпляр этого класса, затем используйте переменную класса, однако необходимость в этом должна быть несколько редкой, поэтому подумайте, действительно ли вам нужна переменная класса.

(Отказ от ответственности: я играл только сRuby около 2 недель, так что это в основном не зависит от языка, но я вполне уверен, что он применим к Ruby. Не стесняйтесь исправлять меня, если я ошибаюсь.)

10 голосов
/ 12 марта 2011

В общем случае переменная экземпляра является локальной и сохраняется внутри экземпляра объекта, тогда как локальная переменная является только локальной и сохраняется внутри области действия функции / объекта / блока. Например:

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

В функции greet name - это локальная переменная, которая определяется только внутри этой функции. Переменная name устанавливается в первой строке функции, name = user.name || 'John', но ее значение не сохраняется вне функции. Когда вы пытаетесь вызвать name, вы получаете NameError, потому что имя было определено только как локальная переменная в функции greet.

@name локально для пользовательского экземпляра класса User. Когда вы пытаетесь вызвать его вне этого контекста, вы получаете nil. Это одно различие между локальными и переменными экземпляра, переменные экземпляра возвращают nil, если они не были определены, тогда как локальные переменные не экземпляра вызывают ошибку.

Обратите внимание, что оба типа переменных локальны для определенного контекста. @name определяется в пользовательском экземпляре, поэтому, когда вы вызываете user.name, вы вызываете функцию name в пользовательском экземпляре, в котором определено @name. name определяется только в функции greet, поэтому при вызове p "Hi, my name is #{name}" вы можете получить значение для name, поскольку находитесь в области действия, в которой оно определено.

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