ЗмістНатисність на посилання, щоб перейти до потрібного місця
У Ruby змінні, що починаються з @, @@ та $, мають різні рівні видимості та використання (скоуп). Розглянемо приклади та спробуємо максимально просто пояснити відмінності.
@ або @instance_variable
Змінні, що починаються з @, є змінними екземпляра. Вони належать конкретному об'єкту (екземпляру класу) і є доступними тільки в межах цього об'єкта. Кожен екземпляр класу має свої власні змінні екземпляра. Перевіримо:
class Example
  def initialize(value)
    @instance_variable = value
  end
  def show
    @instance_variable
  end
end
obj1 = Example.new(10)
obj2 = Example.new(20)
puts obj1.show  # Виведе 10
puts obj2.show  # Виведе 20
Метод ініціалізації об'єкта приймає значення і встановлює його у змінну екземпляра (коли ми викликаємо метод show на об'єкті obj1 спочатку виконується ініціалізація а потім сам метод). Метод show повертає значення змінної екземпляра.
Тобто змінна яка задається за допомогою символу @ дає можливість шейрити значення серед методів класу в контексті об'єкту. Кожен новий об'єкт, наприклад obj2 буде мати своє значення у змінній @instance_variable.
@@ або @@class_variable
Змінні, що починаються з @@, є змінними класу. Вони спільні для всіх екземплярів класу. Якщо одна з змінних класу змінюється в одному екземплярі класу, ця зміна буде видима в усіх інших екземплярах цього класу.
Простий приклад:
class Example
  @@class_variable = 0
  def self.increment
    @@class_variable += 1
  end
  def self.show
    @@class_variable
  end
end
Example.increment
Example.increment
puts Example.show  # Виведе 2
Тобто змінні класу впливають на всі об'єкти цього класу. Іноді це доволі небезпечно і треба бути дуже уважними, щоб не наробити шкоди вплинувши на всі об'єкти.
$ або $global_variable
Змінні, що починаються з $, є глобальними змінними. Вони доступні з будь-якої частини програми, незалежно від області видимості. Використання глобальних змінних може ускладнювати відстеження стану програми, тому їх варто уникати, якщо це можливо.
Приклад:
$global_variable = 10 def show_global $global_variable end puts show_global # Виведе 10
Приклад не дуже наочний, але технічно - ця глобальна змінна може бути змінена та використана будь-де в програмі.
Коротко підсумовуючи
- @instance_variable: змінна екземпляра, унікальна для кожного об'єкта.
 - @@class_variable: змінна класу, спільна для всіх екземплярів класу.
 - $global_variable: глобальна змінна, доступна з будь-якої частини програми.
 
Ну й вчимось писати тести - завжди можна перевірити якісь твердження за допомогою тестів.
test.rb
require 'rspec'
class Example
  @@class_variable = 0
  $global_variable = 0
  def initialize(value)
    @instance_variable = value
  end
  def increment_class_variable
    @@class_variable += 1
  end
  def increment_global_variable
    $global_variable += 1
  end
  def instance_variable
    @instance_variable
  end
  def self.class_variable
    @@class_variable
  end
  def self.global_variable
    $global_variable
  end
end
RSpec.describe 'Різні типи змінних' do
  before do
    @example1 = Example.new(1)
    @example2 = Example.new(2)
  end
  context 'змінні екземпляра' do
    it 'унікальні для кожного об\'єкта' do
      expect(@example1.instance_variable).to eq(1)
      expect(@example2.instance_variable).to eq(2)
    end
  end
  context 'змінні класу' do
    it 'спільні для всіх екземплярів класу' do
      @example1.increment_class_variable
      @example2.increment_class_variable
      expect(Example.class_variable).to eq(2)
    end
  end
  context 'глобальні змінні' do
    it 'доступні з будь-якої частини програми' do
      @example1.increment_global_variable
      @example2.increment_global_variable
      expect(Example.global_variable).to eq(2)
    end
  end
end
rspec test.rb ...Finished in 0.01932 seconds (files took 0.28601 seconds to load) 3 examples, 0 failures
Цей допис поки що не має жодних доповнень від автора/ки.