20170807 - Explanation of the ‘self’ keyword in Object Oriented Programming

This is a reproduction of a forum post I wrote for my CoderAcademy classmates earlier in the course, some had no prior programming experience.


Example ruby code to illustrate the self keyword.

I just wanted to share what I think might be a simpler example to clarify the concept of self that was covered in class today.

This code snippet shows two classes, where one class has a method that takes in objects of the other class.

A printer object (as specified by the Printer class) provides us with a method to print a test page, however it requires that it be provided with a paper object (an object created from the Paper class) to print on.

The Printer class takes in objects of the Paper class.

In my example the method is called at line 23, outside of either class, in such a case we pass it our paper object (which we’ve named a_test_paper_object) as an argument.

We were able to pass the paper object as an argument because we had just declared it a few lines back in the same (main) part of our program.
But what happens if you need to call it from within another class, specifically a class of type Paper. You would have an object of type Paper calling a method in a printer object that requires it be passed a paper object (line 15 & 16). That’s where ‘self’ comes in. The self keyword allows an object to refer or point to itself, at line 23 our main program calls the print_test_page method which you could imagine then asks “on what am I to print?” and the main program points to the paper object created just moments ago. Then on line 27 (through line 16) our paper object calls the print_test_page method itself which then asks “on what am I to print?” and the paper object then points to itself. In both cases the printer object is having its print_test_page method called and in both cases it’s being given the exact same paper object to do the printing on, it’s just that on one hand that request came from our main program and on the other hand it came from the peice of paper itself!

If this isn’t clicking with you it could be the way you’re imagining the computer to be running the code (at least this was my issue back at uni). You can’t imagine that the computer is executing your code line by line from the top down how you’ve written it. Rather, it can jump around between different places in your code.

In the example code here (regardless of what actually happens behind the scenes) it would help to imagine that the code actually starts on line 20, at the creation of a new paper object. Everything that is before line 20 was just us declaring a couple of classes and specifying what the computer will do if we end up invoking one of those classes via the creation of a new object.

On line 20 we set a new variable to be a paper object. Part of the creation of that paper object is the execution of the code within the Paper class’s initialize method. So now you can imagine the computer has ‘jumped’ from line 20 to line 9 then 10 where it creates its instance variable called content and sets it to an empty string. It then moves to line 11, where it sees that was the end of all it had to do and so it ‘returns’ (or jumps back) to line 20. So far it has basically done two things, created a new paper object, and made our variable called a_test_paper_object point to it.

If you’re thinking that the computer executes the code line after line from the top down (like a young Alex once thought when he was stuck on concepts of objects back at uni!) then that would be where you’re getting stuck on the concept, when it hits line 1 it doesn’t create a new printer object, arguably it doesn’t do anything at all except file the information away in the background for when it does need to actually do something with it (like at line 21 when we create a new printer object).

Another issue I had with the concept when I was coming to terms with it at uni was that I didn’t understand the benefits of classes/objects when they seem to make things so confusing. My code used to be a simple set of instructions, and the computer just worked its way down them and it’s simple, introduce classes and it makes my code harder to follow, the execution now jumps from line to line (and we haven’t even pushed our classes out to other separate files yet!).

From where I am now the benefits seem obvious, but back then they weren’t because I kept internally complaining about the concept and I didn’t open my mind enough to fully grasp it and appreciate it.
The true power this gives you is the abstraction, you don’t have to hold every line of your code in your head to understand how it works so don’t try to.

When I was initially new to all this I think where I went wrong is that I would try to mentally trace the path of execution through the code, which meant a lot of jumping between different files, and between different methods and functions. That was how I tried to get a grasp of how the code worked and that was why I mistakenly believed classes, objects and splitting code up into multiple files was confusing and inefficient.

I don’t try to mentally trace code anymore these days unless I’m trying to debug something and even then it’s not through multiple files, its more like 3 lines of code in a single method. Instead I just need to understand what it is a class is supposed to do and take a step back to look at the program in the big picture, or in other words, from a higher level.





back