Understanding global variables

Hi,

I thought that I understood the different type of variables in Ruby but
now that I’m actually trying them I see that I didn’t, reading is easy
putting things in practice is hard.

class Car
@mil_gal = 30
@fuel_gal = 10

def go(mil_gal, fuel_gal)
@mil_gal = mil_gal
@fuel_gal=fuel_gal
millage =@mil_gal * @fuel_gal
puts millage
end
end

car = Car.new
car.go(10,50)

In the above code I have two global variables @mil_gal = 30 and
@fuel_gal = 10, well let me rephrase this in my eyes they are global
variables… but if I change them to mil_gal = 30 and fuel_gal = 10 they
actually work.

#code after changed, which also works
class Car
mil_gal = 30
fuel_gal = 10

def go(mil_gal, fuel_gal)
mil_gal = mil_gal
fuel_gal=fuel_gal
millage =mil_gal * fuel_gal
puts millage
end
end
car = Car.new
car.go(10,50)

If what I have here are not global variables can someone explain this a
little bit? I thought that by adding @ it would make it global and
since I can use this inside other defs I was assuming that they were?

Thanks a lot

hi fily,

as 7stud says, the “@” variables are not global, but instance
variables - which means you can pass them between methods (very handy.)
from what i gather of what you’re trying to do with what you’ve written,
i don’t think you actually need instance variables at all, take a look
at this for example:

class Car
def go(mil_gal, fuel_gal)
mileage = mil_gal * fuel_gal
puts mileage
end
end

car = Car.new
car.go(10, 50)
#=> 500

or you could do something like this:

class Car
def initialize(mil_gal, fuel_gal)
mileage = mil_gal * fuel_gal
puts mileage
end
end

car = Car.new(10, 50)
#=> 500
car = Car.new(30,70)
#=> 2100

if you want to use instance variables, you can do something like this:

class Car

def initialize
@mil_gal = 10
@fuel_gal = 50
end

def go(mil_gal, fuel_gal)
@mil_gal = mil_gal
@fuel_gal = fuel_gal
self.mileage
end

def mileage
mileage = @mil_gal * @fuel_gal
puts mileage
end

end

car = Car.new
car.mileage
#=> 500
car.go(30, 70)
#=> 2100

and if you want to pass those instance variables outside of the class,
and be able to change them, you can do something like this:

class Car

attr_accessor :mil_gal, :fuel_gal, :mileage

def initialize
init_mil_gal = 10
init_fuel_gal = 50
self.go(init_mil_gal, init_fuel_gal)
end

def go(mil_gal, fuel_gal)
@mil_gal = mil_gal
@fuel_gal = fuel_gal
end

def mileage
@mileage = @mil_gal * @fuel_gal
end

end

car = Car.new
puts car.mil_gal, car.fuel_gal, car.mileage
puts
car.go(30, 70)
puts car.mil_gal, car.fuel_gal, car.mileage
car.mil_gal = 38
puts
puts car.mil_gal
puts car.mileage

drive on,

  • j

Fily S. wrote in post #992901:

Hi,

I thought that I understood the different type of variables in Ruby but
now that I’m actually trying them I see that I didn’t, reading is easy
putting things in practice is hard.

class Car
@mil_gal = 30
@fuel_gal = 10

def go(mil_gal, fuel_gal)
@mil_gal = mil_gal
@fuel_gal=fuel_gal
millage =@mil_gal * @fuel_gal
puts millage
end
end

car = Car.new
car.go(10,50)

In the above code I have two global variables @mil_gal = 30 and
@fuel_gal = 10,

Wrong. In ruby, global variables start with a $ sign and they are
visible everywhere(that is except for the regex ‘global’ variables that
ruby predefines). Don’t use global variables.

well let me rephrase this in my eyes they are global
variables…

You may think those variables are global to the class, i.e. they can be
referred to in any method definition–but they cannot. “Instance
variables”, the ones that start with ‘@’ attach themselves to whatever
object is self at the time they are created, and inside a class
definition but outside of any method definitions self is equal to the
class:

class A
puts self
end

–output:–
A

In your case, the instance variables attach to the class, and therefore
you must use the class to access them:

puts Car.mil_gal

Those are known as “class instance variables” and are preferred over
class variables, e.g. @@mil_gal.

On the other hand, a variable that is visible in all method definitions
within a class is called an “instance variable”, and it begins with “@”
and it is created inside a method definition to get the behaviour you
want. Inside a method definition, self is equal to the object that
called the method, so the instance variable attaches to that object.

In ruby, classes carry the common methods of all instances of the class,
and each instance has its own instance variables. The implication of
that state of affairs is that instances of the same class do not
necessarily have the same instance variables:

class A
def initialize
@val = 10
end

def set_name(str)
@name = str
end

attr_reader :val, :name
end

x = A.new
y = A.new
y.set_name(‘Mary’)

puts y.val
puts y.name

puts x.val
puts x.name

–output:–
10
Mary
10

Wow, a little confused, I’m a little disappointed that the language its
self seems to be easer but a simple concept as variables seems a little
complicated (Its probably just me).

This may be confusing because I have never heard about “SELF” statement,
“INITIALZE” method and the “:” notation, I guess I need to read more
about the language.

To make this short what I was trying to say with GLOBAL is accessible in
all methods within the class because I now remember reading what 7stud
said (do not use global variables) in a book.

What would happen if I position a variable using the wrong syntax? In
other words if I position a variable where an instance variable would
normally go but without the @ will Ruby get confused and treat this
differently and may get an error or the interpreter will simply use it
and keep track of what kind of variable it is by itself.

Any good tutorial about variables in Ruby?

Sorry I’m confused and sorry if I’m confusing you guys,

Thank you for your patience

Thanks for the links I will read them and I’m sure I come back with some
other question.

I hope you guys don’t mind answering boring questions like the ones I
usually ask… :frowning:

Thanks a lot

hi fily -

yeah, stuff gets kind of confusing at first, but you’ll get the hang
of it.

check out this post for a good explanation:
http://continuousthinking.com/2007/6/23/instance-variables-in-ruby

To make this short what I was trying to say with GLOBAL is accessible in
all methods within the class

this is what instance variables (@variables) do…

“def initialize” is the method that is passed when an object is
created:

http://ruby.activeventure.com/usersguide/rg/objinitialization.html

“self” just refers to the object itself, and is not in fact usually
necessary - i just use it for clarity, to keep myself from getting
confused!

  • j

no problem - and don’t worry, the forum is for asking questions. sorry
also if my first reply was overwhelming, might have been too much
information!

-j

Fily S. wrote in post #992993:

This may be confusing because I have never heard about “SELF” statement,
“INITIALZE” method and the “:” notation, I guess I need to read more
about the language.

Knowing which object is ‘self’ is sort of an intermediate topic, but it
is critical to understanding how ruby works.

What would happen if I position a variable using the wrong syntax? In
other words if I position a variable where an instance variable would
normally go but without the @ will Ruby get confused and treat this
differently and may get an error or the interpreter will simply use it
and keep track of what kind of variable it is by itself.

A variable name that is not preceded by an ‘@’, is called a ‘local
variable’, and a local variable ceases to exist once the method ends.
Here is an example:

class Dog
def initialize(a_name, a_color)
@name = a_name
color = a_color #color will cease to exist after method ends
end

def name
@name #same as ‘return @name
end

def name=(str)
@name = str
end

def color
@color #same as ‘return @color
end

end

my_dog = Dog.new(‘Spot’, ‘black’)
#Calling new() automatically causes any initialize()
#method defined in Dog to execute.

puts my_dog.name #=> Spot
my_dog.name = ‘Max’
puts my_dog.name #=> Max

puts my_dog.color #=>

Note that the following ‘getter’ and ‘setter’ methods are so common:

def name
@name #same as ‘return @name
end

def name=(str)
@name = str
end

…that you can replace them by:

attr_accessor :name

and ruby will create the getter and setter methods for you. The
following:

attr_accessor :name

is really the method call:

attr_accessor(:name)

:name is what’s called a “symbol”, which is sort of like a constant
string that has an integer id associated with it. Normally, when you
compare the equality of strings like ‘abc’ and ‘abd’, ruby has to check
each character of the strings for equality. With symbols, ruby just has
to check the integer id’s for equality, e.g.

:abc => id = 1234
:abd => id = 5678

so to compare the symbols :abc and :abd, ruby just compares their ids:

if (1234 == 5678)
puts ‘the symbols :abc and :abd are equal’
else
puts ‘they’re not equal’
end

…which is more efficient than comparing every character of the symbol.
A
lot of ruby methods take symbols as arguments, and attr_accessor() is
one of them.

Any good tutorial about variables in Ruby?

“Beginning Ruby (2nd ed)” by Cooper

Thank you all very much!

I would lie if I say that I now understand everything you guys have
explained but a lot of thing make a lot more sense.

Also part of the confusion is that in other languages like Actionscript
3.0 you define your instance variables outside the methods and I was
expecting the same concept in Ruby where variables inside methods cannot
be accessed from outside code.

I will be reading more about the language.

Learning a lot!