Object-Oriented Programming

Melissa Mullen
simple CS
Published in
8 min readSep 2, 2020

Understanding Object-Oriented Programming is one of those things that sets beginner programmers apart from intermediates. The term itself sounds fancy and intimidating, but my hope is that after reading this article, you’ll never want to go back to functional programming.

Functional vs. Object-Oriented Programming

Functional programming is the kind of programming you’ve likely done up to this point. The code runs using only the abstraction of functions. In computer science, an abstraction is an important concept that you will encounter frequently. It involves removing the nitty-gritty details and focusing on big picture functionality. A function is an abstraction, since we only see the function name (without the definition) in the main script. A user can call the function without necessarily understanding how it was implemented.

A function abstraction.

There are other kinds of abstractions, one of which is called a class. A class is a collection of related variables (called attributes) and functions (called methods). Classes are useful for combining data and functionality in a process called encapsulation. For example, we can define a class called Person. We can associate data with a person (name, age), as well as functionality (introduce_self()). We can define this class as follows.

A class is just a user-defined blueprint (just like a function) — it doesn’t contain any user data until we call it and pass it input arguments.

The method defined on line 3 of our class definition, __init__(self, name, age), is the constructor method of our class. The constructor method is run when we instantiate a class, like this:

The constructor method is in charge of assigning input variables to class attributes that can be accessed in any method of the class (without passing them as input arguments to the method). This is done using self . When a class is instantiated, the instance is called an objectself is a way of referring to the object from within the class definition, even before it is instantiated. Class attributes can be called from within a class using self.<attribute>, and class methods can be called from within a class using self.<method>.

In this case, the variable jane is an object. We can “tell jane to do something” (have the object jane run one of its methods), like so.

The output to the terminal will be the following.

Hello, my name is Jane. I am 37.

Note that we could have accomplished this task using functional programming. We could have defined a function introduce(name, age) like this.

If we call the function introduce() with input arguments “Jane” and 37, we get the exact output we had when we created a Person object and called it’s introduce_self() method. The difference is that the function introduce() is not part of any larger abstraction — it exists alone and can be used by anyone, at anytime in a script. The introduce_self() function exists only within the abstraction of the Person class. It can only be called using dot-notation on an object (jane.introduce_self()). More precisely, if we tried to run introduce_self() on its own, we would get a NameError telling us the function we are trying to call is not defined.

Benefits Of Object-Oriented Programming

Inheritance

Suppose we decide to create two other classes called Engineer and Teacher. We want these classes to have all of the same attributes and methods as the Person class plus more attributes and methods. Instead of including the attributes and methods that already exist in the Person class, we can have the Engineer and Teacher classes extend from the Person class, like this.

If we do this, then the Engineer and Teacher classes will automatically contain all attributes and methods from the Person class (name, age, introduce_self()), without us having to include that code in the Engineer and Teacher class definitions. That is, the following would be a valid line of code.

The output of this code would be:

Hello, my name is Sally. I am 27.

We call Person the parent class, and Engineer and Teacher the child classes. We say that child classes inherit the attributes and methods of the parent class in a process called inheritance.

We can add additional methods to both Engineer and Teacher, and they will not be added to Person. Methods added to Engineer and Teacher can have the same name or different names. If they have the same name, that is OK! This is because, in object oriented programming, methods are only defined within the scope of the class — outside of the class, those function names are undefined. For example, we can add a method called describe_profession() to both the Engineer and Teacher class and implement it differently in each. This is a powerful concept in computer science called polymorphism.

When we create Engineer and Teacher objects and call describe_profession() on each, we will we see different outputs, depending on the type of object (Engineer or Teacher).

I code software in C.
I teach High School Pre-Calculus.

Note that we do not need a constructor (the __init__() method) in child classes. If an attribute or method is not found for a particular class, its parent class is searched.

It is possible for a child class method to override a parent class method. For example, we can redefine the method introduce_self() in the Engineer and Teacher classes.

Now, when we create Engineer and Teacher objects and call introduce yourself on them, the function will no longer use introduce_self() definition in the Person class.

Hello, my name is Sally. I am 27. I am an Engineer.
Hello, my name is Jeff. I am 31. I am a Teacher.

If we want to add additional methods to the Engineer or Teacher classes, we can just add them as we would any method. However, if we want to add an additional attribute (let’s say, type) to the Engineer or Teacher classes, we need to redefine the constructor(__init__()). Up to this point, the child classes, Engineer and Teacher, have been using the constructor of their parent class (Person) to instantiate the class and create an object. The constructor of Person takes two input arguments: name and age. In our new constructor, we will include these input arguments and our new input argument (type). Within the constructor, we need to ensure that all input arguments become attributes of the class. To do this, we write self.type = type to define our new attribute — but to define the parent attributes, we can just run the parent constructor. We can access the parent of any child object using super() (which is analogous to how we can use self to access the object itself). That is, to run the constructor of the parent object, we can just run super().__init__(name, age), calling the constructor method of the parent object, and passing the input arguments to the child object on to the parent object. Note that in the following code, I have updated the introduce_self() methods of the child classes to use our new attribute type.

Hello, my name is Sally. I am 27. I am a Software Engineer.
Hello, my name is Jeff. I am 31. I am a High School Teacher.

Abstraction

Inheritance is a means of implementing abstraction. When you create a class, knowledge of its implementation is not necessarily needed for use. For example, any engineer can use our Person class if we provide them with the call signature and the methods. Together, this information is called an Application Programming Interface (API). The API documentation for our Person class might look something like this:

# The Person Class# Syntax
person = Person(name, age)
# Attributes
name : str
age : int
# Methods
introduce_self()

Any engineer could look at this documentation and use our Person class, without ever seeing the class code itself. Companies like Google, Amazon, and Apple capitalize on this concept, allowing users to use their software, but not see how it is implemented.

Abstraction is also a useful concept in designing code. It allows you to focus on the big picture of your design, and helps with organization. For example, now that you are familiar with classes and inheritance, the next time you want to write code you should start by creating a software design. (Remember, software is just a set of instructions for your computer, so your Python code is software!) A software design for our Person/Engineer/Teacher classes example (or Person class hierarchy) might start out looking something like this.

Software design for the Person class hierarchy.

We could expand on our design by adding attributes and methods to each class.

UML Diagram

This visual representation of our Person class hierarchy is called a Unified Modeling Language (UML) Class Digram. UML Class Diagrams are a useful software design technique, providing information about the relationship between classes in the hierarchy, in addition to the attributes and methods associated with each. This is helpful for understanding the design on a high-level, without worrying about the details of implementation (which is the definition of abstraction). You can make this kind of diagram before you even write any code.

Object-Oriented Programming Languages

An object-oriented programming language is a programming language built entirely on objects. That is, no variables or functions can exist unless they exist within an object. Python is unique in that, while it is considered an object-oriented programming language, it also supports functional programming. Many languages only (unless you include lambdas) support object-oriented programming. That is, you can’t write a function and then use that function in a script — the function needs to be contained within an object (making it a method). Some such languages include:

  • Java
  • C++

Final Thoughts

Ultimately, it is up to you whether or not you take an object-oriented or functional approach to your project. Making that decision really comes down to the size of your project. If it is a big undertaking, an object-oriented approach will help with organization and future development. If it is just a matter of making a few computations, a functional approach might make more sense. At least now, after reading this, you can hopefully make an informed decision.

--

--