← homeProgramming (Програмування)

What is the difference between variables that start with @, @@, and $?

Interview question. What is the difference between variables that start with @, @@, and $?

Table of contentsClick link to navigate to the desired location
This content has been automatically translated from Ukrainian.
In Ruby, variables that start with @, @@, and $, have different levels of visibility and usage (scope). Let's look at examples and try to explain the differences as simply as possible.

@ or @instance_variable

Variables that start with @ are instance variables. They belong to a specific object (instance of a class) and are accessible only within that object. Each instance of a class has its own instance variables. Let's check:
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  # Will output 10
puts obj2.show  # Will output 20
The object initialization method takes a value and sets it in the instance variable (when we call the show method on the obj1 object, the initialization is executed first and then the method itself). The show method returns the value of the instance variable.
That is, a variable defined with the @ symbol allows sharing values among the class methods in the context of the object. Each new object, for example, obj2 will have its own value in the @instance_variable.

@@ or @@class_variable

Variables that start with @@ are class variables. They are shared among all instances of the class. If one of the class variables is changed in one instance of the class, that change will be visible in all other instances of that class.
A simple example:
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  # Will output 2
That is, class variables affect all objects of that class. Sometimes this can be quite dangerous, and one must be very careful not to cause harm by affecting all objects.

$ or $global_variable

Variables that start with $, are global variables. They are accessible from any part of the program, regardless of the scope. Using global variables can complicate tracking the state of the program, so they should be avoided if possible.
Example:
$global_variable = 10

def show_global
  $global_variable
end

puts show_global  # Will output 10
The example is not very illustrative, but technically - this global variable can be changed and used anywhere in the program.

In summary

  • @instance_variable: instance variable, unique to each object.
  • @@class_variable: class variable, shared among all instances of the class.
  • $global_variable: global variable, accessible from any part of the program.
And we learn to write tests - you can always check some assertions using tests.
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 'Different types of variables' do
  before do
    @example1 = Example.new(1)
    @example2 = Example.new(2)
  end

  context 'instance variables' do
    it 'are unique to each object' do
      expect(@example1.instance_variable).to eq(1)
      expect(@example2.instance_variable).to eq(2)
    end
  end

  context 'class variables' do
    it 'are shared among all instances of the class' do
      @example1.increment_class_variable
      @example2.increment_class_variable
      expect(Example.class_variable).to eq(2)
    end
  end

  context 'global variables' do
    it 'are accessible from any part of the program' 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

🔥 More posts

All posts
Scope of a local variable in Ruby
Programming (Програмування)Jun 3, '24 16:46

Scope of a local variable in Ruby

The scope of local variables in Ruby. Examples of how variable visibility works in Ruby.

What is immutability and mutability?
Programming (Програмування)Jun 19, '24 07:48

What is immutability and mutability?

What is immutability and mutability? A description of the term in the context of programming and ...

What is a function in programming?
Programming (Програмування)Jun 24, '24 18:15

What is a function in programming?

What is a function in programming? Example of a function in Ruby and JavaScript

How to make an empty git commit?
Programming (Програмування)Jun 28, '24 08:33

How to make an empty git commit?

How to make an empty git commit? Let's make an empty git commit. Why? Who knows, everyone has the...

Ruby library Gosu for creating 2D games
Programming (Програмування)Jun 29, '24 08:48

Ruby library Gosu for creating 2D games

Ruby library Gosu for creating 2D games. Description of the library for game development in Ruby ...