Instance variables in Ruby
Basic elements of Ruby objects, instance variables are used to hold the state or information particular to each distinct instance of a class.
Definition and Scope
In Ruby, an instance variable is a variable that stores an object’s state. In Ruby, an instance variable is a variable that belongs to a specific instance (object) of a class. Each object created from the same class will have its own independent set of instance variables, allowing them to store unique data. An instance variable is also known as a non-static variable or a field.
Naming Convention: By using the single at sign (@
) before their name, instance variables can always be identified (e.g., @name
or @foobar
). One lexical rule that controls variable names in Ruby is the @
prefix.
Scope: An instance variable’s scope is object-wide. They can be accessed from any instance method that is defined in the class of the object. They can also be used to set and retrieve an object’s properties.
Uninitialized Value: It returns nil
if an instance variable is referenced before it has been initialized or given a value.
Persistence: In contrast to local variables that are defined inside a method (such as initialize
), instance variables are retained for the duration of the object instance.
Uniqueness: Because each object retains an own set of instance variables, different instances (objects) of the same class do not share them.
Encapsulation and Access
Ruby upholds a rigorous object encapsulation strategy.
Privacy: Only the object instance that owns the instance variables is privy to them. Accessing or changing an instance variable directly is not possible from outside code, not even from other objects of the same class.
Access via Methods: It is necessary to invoke an expressly specified getter or setter method in order to access or change the value of an instance variable from outside the object. We call these techniques attribute accessor methods. Ruby makes defining these accessor methods simple, simulating instance variable access.
Initialization
Class.new
is usually used to create a new instance of the class, and instance variables are created and initialized within the specific initialize
method (the constructor). Initialize
main task is to create instance variables and set their initial values, which are frequently obtained from arguments supplied to new.
The fact that instance variables in Ruby are not created until they are defined typically by being given a value must be understood. Giving an instance variable a value causes it to “come into existence” for that object.
Code Example: Defining and Using Instance Variables
In the example below, initial_age
is a local variable, and @
name and @age
are instance variables:
class Person
# 1. Accessor methods (Getters) defined here:
attr_reader :name, :age
# The constructor: automatically invoked when Person.new is called.
def initialize(person_name, initial_age)
# @name and @age are instance variables that store the object's state.
@name = person_name
@age = initial_age
# This is a local variable; it dies when initialize finishes.
local_age_check = initial_age
end
# Instance method that can access instance variables (@name)
def introduce
puts "Hi, I'm #{@name} and I am #{@age} years old."
end
# This method cannot access the local variable 'local_age_check'.
def check_local
puts local_age_check # Throws an error (NameError)
end
end
# Create instances
p1 = Person.new("Alice", 30)
p2 = Person.new("Bob", 25)
# Accessing instance variables via accessor methods (getters):
puts p1.name # => "Alice"
puts p2.age # => 25
# Note: @name and @age are unique for p1 and p2.
p1.introduce
# Output: Hi, I'm Alice and I am 30 years old.
# p1.check_local would throw a NameError
Output
Alice
25
Hi, I'm Alice and I am 30 years old.
Code Example: Instance Variables vs. Variables in Class Scope
It is essential to distinguish between a variable prefixed with @
that is defined directly within the class body but outside of any method definitions and an instance variable defined inside an instance method (such as initialize
):
class MyClass
@class_level_var = 1 # This is a Class Instance Variable, owned by the Class object itself.
def do_something
@instance_level_var = 2 # This is a regular Instance Variable, owned by instances of MyClass.
end
def output
# This accesses the Instance Variable set in do_something
puts @instance_level_var
end
def self.read_class_level_var
# This class method can read the Class Instance Variable
@class_level_var
end
end
instance = MyClass.new
instance.output
instance.do_something
instance.output
puts MyClass.read_class_level_var
instance.read_class_level_var
# Throws a NoMethodError unless defined as an instance method.
Output
nil (because @instance_level_var is not yet set)
2
1
The class object itself (a class instance variable) owns the instance variable @one
when it is defined right beneath class MyClass
; this is not the case for the ordinary instances created by MyClass.new
. Class methods are the sole way to access this value. The @instance_level_var
defined in do_something
, on the other hand, is a part of the particular instances and is available to other instance methods.