Home
1/10/20152
1/4/2015
12/28/2014
12/14/2014
12/13/2014
12/6/2014
11/30/2014
11/29/2014
11/23/2014
11/22/2014
11/15/2014
11/12/2014
11/8/2014
11/1/2014
10/31/2014

December 6
2014

Variable Scope

In Ruby, variables act as the pointers to the location of other data. Although they appear to, they do not store the data itself. They only act as a reference to a memory location that some data has been stored in. Regardless of the specifics of how they work, if you assign two different values to the same variable, the first value will be lost. Variables can only store one object at a time. To cope with this variables are given scope. Scope denotes where a variable is visible. If you try to access a variable outside of its scope you will get an error.

The broadest scope is given to constants. Constants have what is called a global scope. That means they can be seen anywhere within your code. Constants are mathematical values that are the same regardless of what your code is doing. They represent basic laws of the universe, like pi or e. In addition to the preset "laws of the universe", you as the programmer can create your own constants. Once you assign a variable, that is named with ALL_CAPITAL_LETTERS, a value that variable is now a constant and will behave in all the ways of the mathematical constants. Despite the name constant, they are actually just like any other object in Ruby. They have attributes and methods that can be used to manipulate the constant itself. Of course this is not recommended, and even if you mean to do it, Ruby will send you a warning.

irb(main):001:0> MY_NEW_CONSTANT = 100
=> 100
irb(main):002:0> MY_NEW_CONSTANT = 200
(irb):2: warning: already initialized constant MY_NEW_CONSTANT
(irb):1: warning: previous definition of MY_NEW_CONSTANT was here
=> 200

There are also global variables. These are similar to constants, because they can be accessed anywhere in the program. They are represented by starting with a dollar-sign($), and unlike constants, you get no warning if you change a global variable. This can make global variables dangerous to use. Often times you'll use variables of the same name as counters or as temporary placeholders. If those variables have a global scope you may get unexpected results.

irb(main):001:0> $my_global_variable = 50
=> 50
irb(main):002:0> $my_global_variable = 25
=> 25

If you want to limit the scope of a variable to just a particular class of objects you can use class variables. These are denoted by starting the variable with two at-signs(@@). The example that always comes to mind for the purpose of class variables would be a parking lot. In the lot you have many cars (which are instantiations of the Car class). We would use a class variable to denote how many cars are in the lot (@@number_of_cars). If a car leaves or enters, it changes the class variable to reflect +1 or -1. Every single car in the class Car has this variable with them, and when each Car object was created it inherited access to the @@number_of_cars variable.

class Car
  @@number_of_cars = 0
  def initialize
    @size_of_car = 1 #number of parking spots
  end
  def enter_lot
    @@number_of_cars = @@number_of_cars + @size_of_car
  end
  def exit_lot
    @@number_of_cars = @@number_of_cars - @size_of_car
  end
  def how_many_cars
    @@number_of_cars
  end
end
car1 = Car.new
car2 = Car.new
car3 = Car.new
car1.enter_lot
p car1.how_many_cars
car2.enter_lot
p car1.how_many_cars
car3.enter_lot
p car1.how_many_cars
car2.exit_lot
p car1.how_many_cars
p car2.how_many_cars
OUTPUT:
1
2
3
2
2

The scope of the entire class is too broad if you want to be able to use a variable within a single object though. Since many objects can be instantiated from a single class, and they will all have the same attributes with different values. They can't all be using the same variables. This is where instance variables come in. They are started with a single at-sign(@). These variables are only accessible within the object itself. They are the equivalent of your personal characteristics and thoughts. No matter how much another Person object wishes to do so, without proper access they can not change your weight. This means that only methods that function within the object can affect the variables. If a different object needs to access a variable, then they need a getter or setter to do so.

Getters and Setters are methods contained within an object that allow the object to be accessed externally. Using @weight as an example of an instance variable we can define the weight of a Person object. In order to increase the value of weight, we would need to use the eat_junk_food method to increase your @weight.

class Person
  def initialize
    @weight = 100
  end
  def eat_junk_food
    @weight += 10
  def show_weight
    @weight
  end
end
john = Person.new
puts "At the start I weigh #{john.show_weight}"
john.eat_junk_food
puts "Now I eat junk food"
puts "Now I weigh #{john.show_weight}"
OUTPUT:
At the start I weigh 100
Now I eat junk food
Now I weigh 110

The last kind of variable, with the most limited scope, is the local variable. Local variables can only be started with lowercase letters or underscores(_). They can only be accessed in the block that they were created. Local variables should be used for internal calculations.

class Person
  def initialize
    @weight = 100
  end
  def eat_junk_food
    @weight += 10
  def show_weight
    @weight
  end
  def show_weight_in_kilograms
    kilos = @weight / 2.2   end
end
john = Person.new
puts "At the start I weigh #{john.show_weight}"
puts "In kilograms that is #{john.show_weight_in_kilograms}"
puts "But I can not access the 'kilos' variable"
puts kilos
OUTPUT:
/Users/John/Desktop/DevBootCamp/nimylian.github.io/blog/untitled.rb:25:in `<main>': undefined local variable or method `kilos' for main:Object (NameError)
At the start I weigh 100
In kilograms that is 45.45454545454545
But I can not access the 'kilo' variable