Disclaimer: The following content is not officially affiliate with Microsoft.
I was taught the concept of Object-Oriented Programming (OOP) really badly when I was at university. I wish I hadthis explanationwhen I was introduced to OOP in my Java course. One thing that I never really understood was why is OOP important. My code works, why do I have to change it to morph it into this OOP design?
The answer is quite simple: reusability, simplicity and security. I thought it was because programmers wanted to befancy(which in some ways, is true). So rather than telling youwhatOOP is, I’m going to start with thewhybecause I think it provides a much more convincing argument as to why we should write code in a OOP design.
So why write code in an OOP design?
I mentioned reusability just before so let’s look at a simple flower example at why reusability is important.
People often ask me how I make my drawings and I’m going to be honest, I use a more advanced version of Paint called Microsoft Whiteboard and this is usually the design process.
I’ll start by building my flower up component by component:
Why build my flower up in this component-by-component way?
This allows me to reuse components. Let’s imagine I wanted to build a different color flower, I simply have to change the color properties of a few of the components and reuse the rest to build a different color flower. So reusability is key.
What is another?
I mentioned simplicity as well. By breaking it down into components, I can maintain components of my flower without impacting the other components. Imagine if I had stuck this flower to my school exercise book. Now, if I wanted another copy of my flower, I would have to cut it out of my exercise book which if anyone has ever tried to be crafty before would know, cutting out is a lot more difficult than building up. The same logic applies to software code, you can cut and copy code snippets but it is often messy, takes more time and you may end up with duplicates that are often difficult to customize or modify.
So imagine instead of cutting and copying, you could build your code up component by component and customize it as you go. You may end up with a completely new software while reusing a lot of work that either you or someone else has done in the past.
That is sort of the idea behind OOP. Treat everything like objects (or what I have been calling so far as ‘components’) and write program in a way where these objects can interact and build on top of one another like usingLegoto build houses and cities.
First you define these objects using templates, called a ‘class’. A class is like a blueprint for your objects. When you want to create an object, you take that class template which outlines everything you need to build that object and you simply say, “Go create this object for me”.
So every time we instantiate (a fancy word for ‘create a single instance of’) a Flower object through the Flower class template, we have a flower object that gets built with a set amount of petals, leaf, stem and the ability to make our flower either happy or sad.
For example, our Flower class might look something like this:
Now the petals, leaf, stem and emotion are what we call attributes in OOP. You can think of it like default values. You can change these default values using methods which I’ll talk about in a second but let’s discuss why attributes are important.
Why are attributes important?
Attributes allows us to define what our flower object is going to look like. If I said, “Go make a flower” to you, you will probably ask me, “What kind of flower? How many petals. What color? How big do you want it?”
But if I gave you a flower class with some attributes, that saves both you and me some Q&A time hence OOP encourages code simplicity.
You also mentioned methods, what are they?
What if you didn’t like the default values I gave you in the flower class attributes. Let’s say you wanted a flower with more leaves and less petals. How would you change that?
This is where methods (which I often call ‘class functions’) comes in. Methods allows you to modify the functionality or behavior of the class objects you instantiate. So if you want to change the emotion of your flower object, you can call upon the happy() method or the sad() method.
How would these happy() and sad() methods work?
That is where I’m going to introduce one of the first principles of OOP known as ‘abstraction’. Abstraction was possibly one of my favorite phrases to hear when I was at university and that was when the professor would tell us, “you don’t need to know this for the exam.” That was something Ialwaysnoted down. Abstraction in OOP is the same. Abstraction tells us, “Hey, you don’t need to know how this method is implemented behind the scenes. All you need to know is that if you call this method, you should get back what it is promised to do.” In this case, if we called the happy() method, we can make our flower object happy. If we called the sad() method, we can make the our flower object sad.
Now, so far, our flower class doesn’t allow us to modify the number of petals, leaf or stem so let’s add a few more methods to our class to allow us to do that. We’ll add a setPetals() method. This allows us to encapsulate our attributes.
Encapsulationis another principle in OOP. Sometimes we might want to keep certain information private. For example, we might want to allow the number of petals for our flower object to be updated but we don’t want to expose that information to anyone. This flower example may not be the best use case here so let’s think of a different example.
When I was at university, I worked as a TA (teaching assistant) which meant I had to mark assignments and exams. Now, for those of you who have ever been misfortunate enough to have to mark piles of assignments and exams, you would know the pains of “What is this illegible handwriting trying to say?” and “Should I give an extra mark to this student?”. Assignments and exams need to be cross marked to try and mitigate bias like these.
Now, if we were to write some software code to allow our TAs to submit their marking and feedback into a system, this is where we need to think of encapsulation. One requirement of this system is, “We want to allow our TAs to submit their feedback but not view other TA’s feedback because that way our students will get a fair evaluation and score.”
We might declare a private attribute ‘score’ and ‘feedback’ and only allow these to be updated through the ‘updateScore()’ and ‘updateFeedback()’ methods from within the class. There are no methods that allows the TAs to access other TA’s scores and feedback that could cloud their judgement and feedback evaluation.
You’ve just learnt why encapsulation is important. Sometimes we want to keep certain pieces of information private within our class and only allow access to things that can be public. This is a principle that supports how OOP encourages security in code design.
I’m no florist but even I know there are different types of flowers such as ‘Sunflower’, ‘Daisies’, ‘Orchids’, ‘Lilies’, ‘Poppies’ and so much more.
So in this case, our Flower class is a bit too generic to create any specific type of flower which is why I’m going to introduce the third principle in OOP, known as ‘inheritance’ to overcome this issue.
Inheritance allows us to define a parent-child relationship between classes. This means you can extend the Flower class (which is a superclass) and create a subtype of flower (which is a subclass).
Inheritance allows for code reusability. For example, daisies also have petals, stem and leaf much like any other generic flowers so rather than redefining all of those attributes (and methods) in the Daisy class, we can inherit all of those attributes and methods from the Flower class. On top of that, there are also specific characteristics to Daisies e.g. they are generally small, have lots of petals, are white in nature, etc. We can specify all of theses specifics within the Daisy class.
Another important concept to note here is that you can override methods from a subclass or overload methods within the same class. This is touching on the last principle of OOP which I’m going to discuss, called ‘polymorphism’.
For the longest time, I never really understood the difference between inheritance and polymorphism but to boil it down to the basics, inheritance allows you to share characteristics and behaviors, polymorphism allows you to change or modify the shared characteristics and behaviors.
Example. We learned that we can create a Daisy subclass to represent a more specific type of Flower class. And our Daisy class inherits all thetraitsthat is defined in our Flower class but what if there are sometraitswe want to change?
For instance, in our Flower class earlier, we said there would be a ‘setPetals()’ method that allows you to determine the number of petals in a Flower object. What if a standard flower only has 5 petals but a Daisy flower has 20 petals?
In this case, we can override the ‘setPetals()’ method in our Flower class with a ‘setPetals()’ method in the Daisy class.
That way, when we instantiate the Daisy object and call ‘setPetals()’, we will have the numbers of petals set to 20 instead of 5.
The other way that polymorphism works in to overload methods within the same class. For example, we can create different types of flowers within the Flower class by overloading some of the methods inside the Flower class.
You might be wondering (because I sure did), why should you polymorph with one approach over the other?
ThisarticleI found gave a pretty good example using a calculator which I’m going to steal so no more flower examples.
Overloading is also known as compile time polymorphism. Basically that means the compiler figures out which method to use at compile time.
Let’s say you had 3 methods in a Calculator class. These methods allow us to sum up some numbers together.
- intsum(intx, inty)
The first sum method takes in two parameters, x and y which are both of Integer type. The return value is also anInteger type.
So if we called something like: Calculator().sum(2, 2). We get 4 back.
2. doublesum(doublex, doubley)
The second sum method takes in two parameters again, x and y however this time, they are both Double type. The return value is alsoDouble type.
If we called: Calculator().sum(2.0, 2.0). We get 4.0 back.
The third sum method takes in two parameters once again, x and y but this time it is one Integer type and one Double type. The result value is returned as a Double type.
If we called: Calculator().sum(2, 2.0). We get 4.0 back.
Overloading is a great demonstration of simplicity. We have simplified our class methods to use the same name, ‘sum’ that can accept different types (and often times different amounts) of parameters. At compile time, depending on which argument types are passed through to the methods, the compiler determines if it will execute ‘sum’ method 1, 2, or 3.
Overriding is also known as runtime polymorphism. Remember the concept of inheritance we talked about earlier, the whole ‘parent-child’ relationship thing with classes. Most parents know that not everything they tell their children will be agreed upon by their children. The same goes for superclass and subclasses in OOP. The subclass (child) may not necessarily agree with everything in the superclass (parent) class. In this case, they have the ability to override certain methods while reusing all the other methods they do agree upon.
This time, we can add more ‘sum’ methods by extending the Calculator class with another class called ‘Math’. The Math class would inherit all of the methods defined in the Calculator class and override the ‘sum’ method with its own implementation. Perhaps, we want our Math calculator to be able to calculate a lot more complex things like a mathematical equation so if we called: Math().sum(“2+2+0”), we get “4” back as a result.
You made it. You just learned about objects, classes, attributes, methods, abstraction, encapsulation, inheritance and polymorphism. And most importantly, I hope you understand thewhybehind coding in OOP design.
As always, I like to make some shout-outs at the end of my blog posts. The first shout-out is to read throughthis blog poston OOP. The second shout-out is a pretty selfish one which is to gofollow meon Twitter for my blog announcements. Don’t forget tofollow meon Medium as well and leave any comments/feedback/criticism behind. If you want, you can always support Explain by Example here.
Once again, thanks for reading. I hope you found it useful 😊