Object Scope and Self

Learn about the scope of an object, the scope of an instance method, and the self keyword.

Remember that when Ruby finds a method call, it deviates from the normal control flow which goes from top to bottom. Instead, it jumps into the method body.

We also learned that this method body has its own scope, like a shiny new room where local variables from other scopes are invisible. Instead, it has its own local variables, some of which might be defined through the method’s arguments.

We also learned that all instance variables inside an object and all its other methods are also visible.

Later, we’ll look at that mysterious top-level object that Ruby enters when it starts executing a program.

We’re now finally ready to put all these things together and introduce a new keyword: self.

The object scope

In Ruby, there are even more scopes than just the local method’s scope. There’s the method’s local scope, which holds all local variables, and there’s the object’s scope, which holds all instance variables and method names.

When Ruby’s control flow jumps into a method, both scopes are visible at the same time. For any given name, Ruby first checks the local scope and then the object scope.

Most importantly, this means that we can access the following from any method in an object:

  • All local variables
  • All instance variables
  • All of the object’s methods

It also means that we can overwrite method names with variable names, sometimes accidentally. Remember that they read just the same in Ruby. While this is a cool feature, we need to be wary of it.

Consider this code:

Press + to interact
class Person
def initialize(name)
@name = name
end
def name
@name
end
def greet(other)
name = other.name
puts "Hi " + name + "! My name is " + name + "."
end
end
person = Person.new("Anja")
friend = Person.new("Carla")
person.greet(friend)

Notice that this defines a new local variable, name. The code is very similar to what we saw in the last lesson, except that in line 11, we store the other person’s name to a local name variable first and then use this variable on the next line when we put our string together.

This breaks our code in the sense that we don’t get the expected greeting anymore. Instead, it contains the same name twice:

Hi Carla! My name is Carla.

That’s because, in line 12 of the greet method, when Ruby looks at the word (identifier) name, it first checks the local scope of the method and finds a local variable defined, so it uses it. It would only check the object’s scope and find the method with the same name and call it if there were no local variable defined.

Remember: When it finds an identifier, Ruby looks for a local variable first and then for a method.

Luckily, there’s still a way to access the object’s scope.

The self keyword

Every object knows itself, in every method, by way of calling self. This is a special keyword in Ruby, which means the object itself.

Let’s try that, and output self. To do that, we need to add it somewhere inside the object. Any method would be good for that, but let’s just use the initialize method:

Press + to interact
class Person
def initialize(name)
@name = name
p self
end
end
person = Person.new("Anja")
p person

As we can see, we output the same object twice. Once in the initialize method using p self, and once in the outer scope using p person. We can also see that the cryptic-looking object ID is the same for both instances. So, we know it’s the same object.

Remember: The object can be referred to using the keyword self inside any method.

So, we can fix our code from above like this:

Press + to interact
class Person
def initialize(name)
@name = name
end
def name
@name
end
def greet(other)
name = other.name
puts "Hi " + name + "! My name is " + self.name + "."
end
end

Now, we call the name method on two different objects again. When Ruby sees self, it knows that we’re referring to the person object, and it calls the name method on it.

This fixes our greeting:

Hi Carla! My name is Anja.

Keywords

Why do we keep saying that self is a keyword? That’s because it’s not a method. It’s a special thing in Ruby. For example, this means that the following raises an error:

Press + to interact
class Person
def initialize(name)
@name = name
p self
end
end
person = Person.new("Anja")
p person.self

It’s not a method, it’s a special thing.

Other keywords that also aren’t methods (or objects, or classes) are, for example, def, class, and end.

Remember: Keywords are words that have a special meaning in Ruby, such as class, def, end, and self.