Нормальные переменные против переменной экземпляра в Ruby, в чем разница?

рассмотрим следующий пример ruby class

class User
  def hello
    puts "hello"
  end
end

Теперь, для инициализации. есть два пути

нормальная переменная

1.9.3p125  > tr = User.new
 => #<User:0x98778c4>
1.9.3p125  > tr.hello
 Hello world
 => nil`

переменные экземпляра:

1.9.3p125 > @tr = User.new
 => #<User:0x9890f2c>
1.9.3p125 > @tr.hello
Hello world
 => nil

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

3 ответов


обычная переменная имеет область действия только в текущем контексте; переменная экземпляра имеет область действия во всем экземпляре класса. В вашем случае они путаются, потому что контекст main, который действует как экземпляр Object.

рассмотрим следующее, что может сделать вещи яснее

class User
  def set_name
    @name = "Bob"
    surname = "Cratchett"
  end

  def hi
    puts "Hello, " + @name
  end

  def hello
    puts "Hello, Mr " + surname
  end
end

irb(main):022:0> u = User.new
=> #<User:0x29cbfb0>
irb(main):023:0> u.set_name
irb(main):024:0> u.hi
Hello, Bob
=> nil
irb(main):025:0> u.hello
NameError: undefined local variable or method `surname' for #<User:0x29cbfb0 @name="Bob">

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

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

также переменные класса local для всех экземпляров класс:

@@class_variable = 'a class variable'

и глобальные переменные доступно из любой точки программы:

$global_variable = 'a global variable'


локальная переменная может использоваться только внутри метода, в котором она определена (или, когда переменная определена на верхнем уровне, только вне любого метода). Переменная экземпляра может использоваться из любого метода, вызываемого в том же экземпляре.

вот пример, где вы можете увидеть разницу:

@tr = User.new

def foo
  @tr.hello
end

foo
# Hello World


tr = User.new

def bar
  tr.hello
end

bar
# Exception because tr is not accessible from within bar