Instance variables have an object wide scope, they can be declared anywhere in the object, however an instance variable declared on class level, will only be visible in the class object. A variable will be considered an instance variable when prefixed with @
. Instance variables are used to set and get an objects attributes and will return nil if not defined.
class Dinosaur
@base_sound = "rawrr"
def initialize(sound = nil)
@sound = sound || self.class.base_sound
end
def speak
@sound
end
def try_to_speak
@base_sound
end
def count_and_store_sound_length
@sound.chars.each_with_index do |char, i|
@sound_length = i + 1
p "#{char}: #{sound_length}"
end
end
def sound_length
@sound_length
end
def self.base_sound
@base_sound
end
end
dino_1 = Dinosaur.new
dino_2 = Dinosaur.new "grrr"
Dinosaur.base_sound
# => "rawrr"
dino_2.speak
# => "grrr"
The instance variable declared on class level can not be accessed on object level:
dino_1.try_to_speak
# => nil
However, we used the instance variable @base_sound
to instantiate the sound when no sound is passed to the new method:
dino_1.speak
# => "rawwr"
Instance variables can be declared anywhere in the object, even inside a block:
dino_1.count_and_store_sound_length
# "r: 1"
# "a: 2"
# "w: 3"
# "r: 4"
# "r: 5"
# => ["r", "a", "w", "r", "r"]
dino_1.sound_length
# => 5
Instance variables are not shared between instances of the same class
dino_2.sound_length
# => nil
This can be used to create class level variables, that will not be overwritten by a child-class, since classes are also objects in Ruby.
class DuckDuckDinosaur < Dinosaur
@base_sound = "quack quack"
end
duck_dino = DuckDuckDinosaur.new
duck_dino.speak
# => "quack quack"
DuckDuckDinosaur.base_sound
# => "quack quack"
Dinosaur.base_sound
# => "rawrr"