What is a practical application of doing this inside a function method?
class Dog
def foo
one = 1
@two = 2
end
def bar
puts @two
puts one
end
end
d = Dog.new
d.foo
d.bar
--output:--
2
1.rb:9:in `bar': undefined local variable or method `one' for #<Dog:0x00000101086810 @two=2> (NameError)
from 1.rb:16:in `<main>'
Local variables, the ones without an @ in front of them, are destroyed when a method finishes executing.
Yes - but what does this mean in a regular function, not a method of a class?
Instance variables, the ones with a single @ in front of them, attach themselves to whatever object is self at the time they are created:
def do_stuff
puts self #=>main
@val = 10
end
do_stuff
puts self #=>main
That output is a little unusual because self is equal to an object called main
both inside the def and outside the def. Usually a def will change self--but a def doesn't change self when the def is at the the top level.
Okay, so if @val attached to an object called main, and self=main, lets print out @val:
def do_stuff
puts self #=>main
@val = 10
end
do_stuff
puts self.val #`<main>': undefined method `val' for main:Object (NoMethodError)
Ahh, yes. All instance variables are private by default, so let's write some accessors in main's class:
def do_stuff
puts self #=>main
@val = 10
end
do_stuff
puts self.class #=>Object
class Object
attr_reader :val
end
puts self.val #=>10
Next, a def attaches to whatever the current class is when the def is created. The current class is either equal to self, or if self isn't a class, then the current class is self's class. In the example above, when do_stuff was created self=main:
puts self #main
def do_stuff
puts self
@val = 10
end
Because self is not a class, the current class is self's class, which we can see is Object:
puts self.class #Object
So do_stuff attaches itself to the Object class, which means it becomes an instance method of the Object class. And for extra points--it actually becomes a private instance method:
puts Object.private_methods.grep(/^do/) #=>do_stuff
defs inside classes also attach themselves to to the current class:
class Dog
puts self #=>Dog
def bark
puts "Woof"
end
end
...but unlike at the toplevel, the defs become public instance methods of the class.