I remembered when I first learned OOP. I was coming from a Functional Programming background and this new way of thinking was giving me some troubles. After much practice once I got a grasp on OOP I love its utility and capability. In this article I want to give you a basic overview of OOP as it relates to real life. My puppers Ada and Taz will help me explain what OOP is and how the 4 pillars of OOP work.
What is OOP?
According to Wikipedia “Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data and code: data in the form of fields (often known as attributes or properties), and code, in the form of procedures (often known as methods)". A programming paradigm, objects, procedures???? What does that even mean?
Let's break this down! OOP is basically a way to structure your code to think more like we do as humans. As humans we think in an OOP way every day. If I told you I have a dog what do you think about? What is its name? Is it a boy or girl? What color is it? We know what a dog is and we know that every dog has certain characteristics. Relating this to our wonderful wikipedia definition: my dog is our object and their color, name etc are all different attributes or properties of a dog object. We also know that dogs like to bark and go for walks. These are all different actions/procedures or methods
that dogs preform. We associate all these topics naturally but a computer doesn’t. This is where OOP comes in. We must structure our code in a way that a computer can make the same connections.
let dog1 = “Ada”
let dog1Color = “Black and Tan”
let dog1Breed = “Bernedoodle”
let dog2 = “Taz”
let dog2Color = “Black and White”
let dog2Breed = “Bernedoodle”
Perfect I just told the computer about my dogs. It will forever know who and what they are right? Unfortunately not. All we are doing above is taking a variable and giving it some name and associating it with some value. The computer only sees dog1 and thinks of the value Ada. It has not idea what Ada’s color or breed is. Sure I can call dog1Color to get the correct color, but the computer has not idea they are associated with each other.
class Dog{
constructor(name, color, breed){
this.name = name;
this.color = color;
this.breed = breed;
}
}
When we use OOP we create a classes and objects. A class is just a blueprint for the computer to call upon. In my dog class above the computer now knows that a dog has a name, color and breed. So whenever I tell the computer I have a dog, It starts to ask the same questions as we did earlier. Whats the dogs name? Whats the dog’s color? Whats the dog’s breed? This is the first step to get the computer thinking similar to us.
const ada = new Dog(“Ada”, “Black and Tan”, “Bernedoodle”)
const taz = new Dog(“Taz”, “Black and White”, “Bernedoodle”)
Now instead of having a dog1 and dog2 variable we now have two dog objects. To the computer ada
and taz
are both objects of the dogs class. The computer then can make the same connections as we do. The computer knows that ada is black and tan and is a Bernedoodle! This is the basics of OOP. We create a class that acts as a blue print and then create objects of that class. This allows our program to think more organically like us, but wait there is more! There are 4 main principles of OOP. Ada and Taz will help give us a brief overview of each.
4 Pillars of OOP
Abstraction
Abstraction is a beautiful thing. It allows us to hide away chunks of code. This is beneficial to keep our code clean and gives us the ability to share code easier. If there was no abstraction we would have to know how everything worked and in what order. An example of abstraction is when I take Ada and Taz for a walk. In order to take them for a walk, I have to grab their leash, put on their collars, grab the poop bags, and make them sit at the door before I let them out. Then we walk and when I get back I have to put everything up. After all this, the dogs are happy and tired as a result. If this was a dog game and I wanted to increase their happiness and make them tired I just want to call the walk method on my dog objects. I don’t care how it works or all the logic. I just need the result. Abstraction allows us to do this. We can create a walk method on our dog class. Inside this method has all the details but when we call this method on any of our dog objects we just see the result we are looking for.
Inheritance
So we know that Ada and Taz are dogs and our computer knows that a dog has a color, name, and breed. It has no idea about anything else. We know that dogs are also mammals. This means by default, dogs have hair/fur, are warm-blooded, and fed milk as a puppy. We can add all these properties to our dog class but what if we wanted to teach our computer about a cow or cat? We would have to do the same “mammal” properties for each one. With OOP we can inherit things from other classes. So if we create a mammal class that has all those properties then we can have our dog, cat and cow class inherit those properties. This way the computer knows that a cat, cow, and dog all have hair/fur, warm-blooded, and fed milk when young. It also knows that a dog has a separate list of properties that makes it different from the other classes. This creates relationships for the computer the same we do when we compare a dog to a cow!
Encapsulation
Encapsulation occurs when you keep something private inside the class. Ada and Taz are smart dogs. They listen when I tell them to sit, stay, lay down, heal, and shake. One thing I have no control over is their bark. They have a mind of there own when it comes to barking. Sometimes its random other times it happens when I do something. This is an example of encapsulation. In our dog class we can create a private method called bark. This method makes our dog bark. Encapsulation keeps me the human class from calling the bark method on Ada and Taz. It is private to just that class. I do know whenever I take Ada and Taz for a walk they get super excited. While I am getting them ready they always bark, especially if I take to long to put my shoes on! In our dog class we can use the private bark method inside of our walk method. So every time I go for a walk the bark method will be called but I can’t make them bark on command since it is a private method.
Polymorphism
Polymorphism gives us even more control over our classes and their inheritance. So far we know that when a child class inherits from its parents class its gets access to all the public properties and methods inside its parents class. Polymorphism allows us to inherit these properties and make them unique to the child class. An example of this is hair. Our parent mammal class has a hair property so our child dog class inherits this. Our computer knows that a dog has hair just like a cow has hair. This is true, but the type of hair is very different. With polymorphism we can make sure that the hair of our dog is fluffy while the hair on our cow is more of a corse hide. Now our computer knows even more information about our classes. It knows that a cow and dog both have hair but with polymorphism it now knows that the hair is different for each class.
I hope that Ada and Taz shined some light on OOP for you. OOP is not as complicated as it seems. You think in an OOP way every day but don’t realize it because it is second nature. OOP is just the art of getting the computer to think in the same manner. I hope this real life example helps clear up any confusion with OOP. Sometimes it helps to relate complex topics to real world objects
; ).
Top comments (8)
OOP is hard. Right when you think got it you then realize you have been over abstracting and your inheritance hierarchy is more like a spider web. This is when you learn about composition over inheritance and need to relearn what you thought was cool about OOP 🤷♂️
Exactly, sometimes has-a is better than is-a, especially for testing.
From GeeksforGeeks "Favoring Composition Over Inheritance In Java With Examples":
This is generally true because of the way class inheritance is usually implemented in languages, but consider the following example in a made-up language:
To some extent, this can even be achieved in languages like Ruby, there's just no nice syntax for it.
That's trivial with C++ templates, but the deeper you get into parametric pymorphism, the more you'll realize inheritance is all downside except for the perceived ease of use of not needing to repeat method definitions on superobjects (those with usually a dozen or more low-cohesion methods).
I think the main benefit of inheritance is how object genealogy can make code more self-documenting as well as make it easier for automated tools to draw conclusions about semantics from the code alone.
Whether this is a good trade-off, I can't really comment on, as I've never seen the appeal of class-inheritance based object orientation.
Regarding the #javascript tag:
MDN: JavaScript:
Depending on the context the "cost" of organizing code in this manner may or may not be appropriate.
Data-Oriented Design: Mapping the problem (2018):
i.e. OOD/OOP should be a deliberate and well-reasoned choice - not a default way of working. JavaScript isn't Java - there is no dogmatic drive towards everything having to start with a class.
This is the best explanation for OOP I've read so far, thanks for sharing this. With constant use of OOP it gets to stick.
See here for very similar post. It seems a bit the power of OO was forgotten when the Web was created...