Змінні у Ruby: @, @@ та class instance variable

Обкладинка допису: Змінні у Ruby: @, @@ та class instance variable
У Ruby існує кілька типів змінних, які відрізняються тим, кому вони належать - об’єкту, класу чи всім нащадкам одночасно. Розберімося просто і з прикладами.

@ - змінна екземпляра (instance variable)

Це звичайна змінна, яка належить конкретному об’єкту. Кожен екземпляр класу (об'єкт) має свою власну копію такої змінної.
class User
  def initialize(name)
    @name = name
  end

  def name
    @name
  end
end

u1 = User.new("Oleh")
u2 = User.new("Ira")

u1.name  # => "Oleh"
u2.name  # => "Ira"
У кожного користувача своє ім’я. @name не ділиться між об’єктами - це їх особисті дані.

@@ - змінна класу (class variable)

Змінна з двома собаками (@@) спільна між усіма екземплярами і підкласами. Вона живе всередині всієї ієрархії класів.
class Animal
  @@count = 0

  def initialize
    @@count += 1
  end

  def self.count
    @@count
  end
end

class Dog < Animal; end

a1 = Animal.new
d1 = Dog.new

Animal.count  # => 2
Dog.count     # => 2
І Animal, і Dog бачать одну й ту саму змінну @@count. Якщо підклас її змінює - це впливає на батьківський клас. Через це @@ вважають небезпечною і застарілою практикою - краще уникати її використання.

Class instance variable - безпечна альтернатива @@

Можна створити змінну на рівні класу, але щоб вона належала лише цьому класу, а не спадкоємцям. Це звичайна @змінна, але оголошена на рівні самого класу (а не всередині initialize).
class User
  @count = 0

  def self.add_user
    @count += 1
  end

  def self.count
    @count
  end
end

class Admin < User; end

User.add_user
User.count   # => 1
Admin.count  # => nil
У цьому прикладі User має свою власну @count, а Admin - окрему (спочатку nil, доки її не визначать). Це робить код безпечним і передбачуваним.

Цей допис поки що не має жодних доповнень від автора/ки.

==, equal?, eql?, === у Ruby: що перевіряють і коли використовувати
29 жовт., 20:47

==, equal?, eql?, === у Ruby: що перевіряють і коли використовувати

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Include, Extend, Prepend у Ruby: як вони працюють і в чому різниця
29 жовт., 21:20

Include, Extend, Prepend у Ruby: як вони працюють і в чому різниця

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
module_function у Ruby: коли методи модуля доступні як модульні та як функції
29 жовт., 21:53

module_function у Ruby: коли методи модуля доступні як модульні та як функції

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Що таке memoization в Ruby?
30 жовт., 10:17

Що таке memoization в Ruby?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
is_a?, kind_of?, instance_of? — як Ruby перевіряє тип об’єкта?
30 жовт., 19:55

is_a?, kind_of?, instance_of? — як Ruby перевіряє тип об’єкта?

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
&& vs and — різниця в Ruby, яка може зламати ваш код
30 жовт., 20:23

&& vs and — різниця в Ruby, яка може зламати ваш код

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska
Різниця між blank?, present?, empty? та nil? у Ruby
30 жовт., 21:06

Різниця між blank?, present?, empty? та nil? у Ruby

Нотатки про Ruby та RoR
Нотатки про Ruby та RoR@kovbaska