The Four Pillars of Object Oriented Programming
Tags: oop, programming
Published: 2020-12-11 00:16:45

Whether you love, or hate, object oriented programming, "What are the four pillars of OOP?" will be a question you get asked on interviews again and again. I know this because a good friend of mine, who is a newly minted CS grad, messaged me upset because she completely blanked on this question during one of her interviews, and I was literally asked this question yesterday during a technical interview. 

Just a quick disclaimer, this post is not an exhaustive and deep dive into the four pillars. I am merely providing quick "in a nut shell" explanations of the four pillars, with the sole aim of helping people answer this question when it inevitably comes up during an interview.

So what are the four pillars of OOP? They are Inheritance, Encapsulation, Polymorphism, and Abstraction. I will start with Encapsulation, which I believe is the real heart of OOP.
Basically, Encapsulation is keeping your state and behavior in the same place. I also like to think of it as a public contract with private implementation. For example, say you have a class called Customer: 
```
class Customer
   def initialize(id, name, addr)
      @cust_id = id
      @cust_name = name
      @cust_addr = addr
   end
   def display_details
      puts "Customer id #@cust_id"
      puts "Customer name #@cust_name"
      puts "Customer address #@cust_addr"
   end
end
```
So, we have this class called Customer, with some instance variables, and a method that displays those instance variables. Those instance variables describe the state of our class, while the method describes the behavior. They are both "encapsulated" inside of our class. The public contract aspect of this that I mentioned earlier, means that this class is guaranteed to have this state and behavior. However, the private implementation aspect that I mentioned comes into play with how I choose to use the class. I could write new methods that display only one of the instance variables, or I could write new methods that add additional behavior. However, the main concept of Encapsulation is that state and behavior are in the same place.

Inheritance is a relation between two classes. We know that all dogs are animals. The benefit of inheritance is that classes lower down the hierarchy get the features of those higher up, but can also add specific features of their own. If all animals breathe, then all dogs breathe. In Ruby, a class can only inherit from a single other class. Some other languages support multiple inheritance, a feature that allows classes to inherit features from multiple classes, but Ruby doesn't support this.
```
class Animal  
  def breathe  
    puts "inhale and exhale"  
  end  
end  
  
class Dog < Animal  
  def speak  
    puts "Woof!"  
  end  
end  
  
doug = Dog.new  
doug.breathe  
doug.speak  
```

Polymorphism comes form the greek words "polys" meaning much or many and "morphe" meaning form or shape. In programming this means that you can have methods that all share the same name, but have different implementations. For example, say you have this class called Person:
```
class Person
    def initialize(first, last, age)
         @first_name = first
         @last_name = last
         @age = age
    end

    def birthday
         @age += 1
    end

    def introduce
          puts "Hi everyone. My name is #{@first_name} #{@last_name}."
    end
end
```
This is all well and good, but let's also say that you want to get more specific with your person, say you also have a class of Teacher, and a class of Student. We want to keep the state and behavior of our Person class, so we will have our Teacher and Student classes inherit from the Person class. The beauty of Polymorphism is that we can keep the original "introduce" method that we get from our person class, and give it new behavior for each of the other two classes like this:
```
class Person
    def initialize(first, last, age)
         @first_name = first
         @last_name = last
         @age = age
    end

    def birthday
         @age += 1
    end

    def introduce
          puts "Hi everyone. My name is #{@first_name} #{@last_name}."
    end
end

class Student < Person
    def introduce
          puts "Hello teacher. My name is #{@first_name} #{@last_name}."
    end
end

class Teacher < Person
    def introduce
          puts "Hello class. My name is #{@first_name} #{@last_name}."
    end
end
```
The Teacher and Student classes both have a method called "introduce," but it behaves differently, or it has a different implementation thanks to polymorphism. We have overridden the original method behavior, but we have kept the same name.

Lastly we have abstraction, which is basically the idea of only showing essential attributes to the user, and hiding any unnecessary details/information. Abstraction is selecting data from a larger pool, and only showing the relevant details of the object to the user. It helps reduce programming complexity. An example that helps me wrap my head around the concept is fetching data from an API. Say you make a fetch request that gives you back 100 blog posts in the form of an array of objects. Each object contains the properties of, title, body, author, publication date, publisher etc. For the purposes of your website, you want to display the first four posts on your page, and only include the title and body. So you write some JavaScript and do some DOM manipulation that allows you to do just that. In this case you have abstracted away all of the posts that you don't want to display, and all of the other object properties that you don't need as well. You still get all of that information when you make your initial fetch request, but you have hidden, or abstracted it away from your user. 

I hope this post has helped someone understand the basics of the four pillars of OOP. Other OOP languages may do things a little differently than the examples I have shown in Ruby, for example you can't overload in Ruby because it isn't a strongly typed language, but the rest of the concepts are pretty much the same across the board.