Finding my.self in Object Oriented Programming

It was a tough and long first week, but I never felt so accomplished. What have I been doing my whole life?

The first wall I hit since starting at Flatiron was when we started learning about Object Oriented Ruby. I was cruising through classes and instances until I hit the “Self” keyword. I kept asking myself, “what is self?”.

First, a brief intro to Object Oriented Ruby: Classes, Instances, and Self

“Object-oriented programming (OOP) is a programming paradigm based on the concept of “objects”, which may contain data, in the form of fields, often known as attributes; and code, in the form of procedures, often known as methods. A feature of objects is that an object’s procedures can access and often modify the data fields of the object with which they are associated (objects have a notion of “this” or “self”). In OOP, computer programs are designed by making them out of objects that interact with one another.[1][2] There is significant diversity of OOP languages, but the most popular ones are class-based, meaning that objects are instances of classes, which typically also determine their type.” — Wikipedia

One easy way to understand the differences between Classes, Instances, and Self are by comparing them to real world objects. In Object Oriented Programming, Classes are like factories and Instances are like the products being produced from the factory. Let’s take a look at the code examples below.

Here we have a simple class (or factory) called CarFactory.

class CarFactory
attr_accessor :name
  def initialize(name)
@name = name
end
  def start_engine
puts "VROOOOOMMM!!!"
end
end

We create an instance of the CarFactory class by calling .new on the CarFactory class and give it a name of mustang.

mustang = CarFactory.new("Mustang")

We can then enact actions on the instance by calling the procedures or methods we previously defined in our class like the #start_engine method.

mustang.start_engine
VROOOOOMMM!!!
=> nil

We can see that the #start_engine method from the CarFactory class was able to call the block of code inside on the instance mustang which then printed out the word “VROOOOOMMM!!!”.

Now we arrive at the big question: what is Self?

What is Self?

Self can be referred to as the instance (the product) of the Class or even the Class itself. This is what makes Self so confusing, it can operate as both. But for now, we will go over the Self keyword operating as an instance.

Here we have the CarFactory class and the mustang instance we made earlier.

class CarFactory
attr_accessor :name
def initialize(name)
@name = name
end
def start_engine
puts "VROOOOOMMM!!!"
end
end
mustang = CarFactory.new("Mustang")

We want the mustang to be registered to an owner. So let’s add the ability to read and write the owner for this new mustang.

class CarFactory
attr_accessor :name, :owner
def initialize(name)
@name = name
end
def start_engine
puts "VROOOOOMMM!!!"
end
end
mustang = CarFactory.new("Mustang")
mustang.owner = "James"
mustang.owner
=> "James"

Now our mustang is registered under an owner and can be rolled out of the factory but let’s say I changed my mind and wanted to sell the car. The car would need to be registered under a new owner. How can we do that? We can do this by creating a new method that gives us the ability to change ownership of the car.

def new_owner(car, new_owner_name)
car.owner = new_owner_name
end
mustang.owner
=> "James"
mustang.new_owner(mustang, "John")
mustang.owner
=> "John"

We can change the owner of the car by setting the owner of the car to the new owner’s name like the example above. But there is an even better way to do this and that is by using the Self keyword.

def new_owner(new_owner_name)
self.owner = new_owner_name
end
mustang.owner
=> "James"
mustang.new_owner(mustang, "John")
mustang.owner
=> "John"

By using the Self keyword, we were able to change the owner of the car without actually having to pass the car that is having it’s ownership changed as an argument in the method. This makes sense because we already know that “mustang” is the instance we want to change ownership of, and it shouldn’t have to pass itself as an argument when the method is being called on itself.

All this talk about Class, Instances, and Self may be overwhelming (since it was for me in the beginning) but once you are able to understand that Self is actually the very instance that we are calling the method upon, it all becomes very clear.

So, what is Self again?

class CarFactory
attr_accessor :name, :owner
  def initialize(name)
@name = name
end
  def start_engine
puts "VROOOOOMMM!!!"
end

def new_owner(new_owner_name)
self.owner = new_owner_name
end
end
corvette = CarFactory.new("Corvette")
corvette.owner = "John"
corvette.new_owner("James")

What is self referring to in the method #new_owner?