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

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

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

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

Ответ 1

Нормальная переменная имеет область видимости только в текущем контексте; переменная экземпляра имеет область видимости для всего экземпляра класса. В вашем случае они запутаны, потому что контекст 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">

Ответ 2

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

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

Существуют также переменные класса, локальные для всех экземпляров класса:

@@class_variable = 'a class variable'

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

$global_variable = 'a global variable'

Ответ 3

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

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

@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