In this post, I’ll talk about several ideas belonging to the world of Object-Oriented Design. It’s easy to interpret Object-Orientation as this academic body of knowledge when you first hear some of these ideas. You’ll hear words like “Polymorphism”, “Abstraction”, “Composition” and many others and it can sometimes sound like a philosophical exercise that just can’t have much in the way of creative or practical value but it is actually the other way around. Programming is always a creative act and Object-Oriented Design is not by itself a formalized process. It is a set of ideas and techniques that you will use as part of your own process.
It’s easy to think that, if you just get started and jump right into a code editor, you can figure out everything else along the way and, more often, it leads to code that’s abandoned…To programs that slow down…The realization that you have to back out days or weeks of work because you should have thought about it just a little bit more before you started typing. So, what you will be learning in this post will lead to a greater understanding of your code.
Understanding Object-Oriented Analysis, Design and Development
When you see the words “Object-Oriented”, you’ll usually see another word right beside them. “Object-Oriented Programming”, “Object-Oriented Design” or “Object-Oriented Analysis”. These are all connected and refer to the idea that, to write any piece of software, we need to do three things:
- Understand our problem (Analysis).
- Plan our solution (Design).
- Build it (Programming).
These all deal with this larger idea of Object-Orientation.
Analysis means understanding the problem (what do we need to do?) and Design is the conceptual design of the solution (how are we going to do it?). By “conceptual”, I mean no code here. Diagrams? Sure…Sketches on a whiteboard? Yes…Written descriptions? Absolutely but no code and the more you understand Analysis and Design, the easier the Programming will be.
I will not make an in-depth study on Analysis or Design in this post since they are complete topics by themselves but I invite you to further investigate them if you do decide to move forward with your OOP learning.
What is an object?
If we want to ask: “What is an object?” in a computer program, we must first ask: “What is an object?” in the real world. So, is an apple an object in real life? Sure. A desk? Of course. They’re objects. We understand that objects are separate from one another.
The three things that describe an object in an Object-Oriented Programming language are:
We can have two apples but they’re not the same object. They have their own identity. Also, we know that objects have inherent properties that describe them. A mug can be full or empty…An apple can be green or red…A lamp can be off or on…These are the attributes of an object (colour, weight, size, etc). Tied to the idea of identity and properties, objects have behaviours in the real world. A telephone can ring…An airplane can fly…And that behaviour is specific to the type of object.
In a computer program, a date could be an object. So does a time or a bank account. You can’t touch and hold a bank account in real life but it is still a well-defined idea and, even in real life, it meets our definition of object. It has identity.
One clue to figure out if something in your application is a new potential object is: If you were talking about it in conversation, could you put the word “the” in front of it? The mug…The apple…The car but you wouldn’t say: “The saving”…”The printing”…”The exploding”…Those would be verbs. They would be behaviours of objects and not objects themselves.
What is a Class?
Objects and Classes go hand in hand. We can’t talk about one without talking about the other and the entire point of Object-Oriented Design is not about objects. It’s about Classes because we use Classes to create objects. So, a Class describes what an object will be but it isn’t the object itself. A Class is a blueprint or a detailed description. If you want to build a house, you make a blueprint first. It describes everything about how that house will be built but it isn’t the house. So, we write the Class. Then, use the Class to create the object and, just as we could use the same blueprint to build one, two or a hundred houses, we can define the Class once and, then, create a thousand objects based on that one Class but the Class comes first and it describes two things: Attributes and behaviour.
In most OOP languages, there are a lot of Classes already written for you that come along with the language so you can start creating objects without writing your own Classes. These Classes are gathered together into frameworks or libraries. Nevertheless, we will still need to write our own Classes in most cases.
What is Abstraction?
There are four fundamental ideas to keep in mind when creating Classes:
One way to remember these is with the acronym “APIE”.
Abstraction means we focus on the essential qualities of a Class rather than one specific example. We automatically discard what’s unimportant or irrelevant to the concept of an object.
Abstraction means that we can have an idea or a concept that is completely separate from any specific instance. It’s at the heart of OOP because it’s what we’re doing when we make a Class. It means that we don’t create one Class for Joe’s bank account and a separate Class for Alice’s bank account in a financial application. We will write a single “BankAccount” Class for all of them.
It might be true that every bank account was opened on a specific date but, if our application doesn’t care about that piece of information, we don’t need that attribute defined in our Class.
What is Encapsulation?
In OOP, Encapsulation refers to the idea of taking our attributes first and, then, taking our behaviours and bundling them together in the same unit (the same Class) but it’s really more than that. The principle is that an object should not reveal anything about itself except what is absolutely necessary for other parts of the application to work.
Think of using a telephone. You want your interaction with a telephone to be limited to just using the keypad to make a call but you don’t want to care about how it works internally. If the inner workings of your telephone completely change, it wouldn’t matter as long as you have the same buttons to press. One of the main benefits with OOP is that it allows us to more safely change the way the object works because we’ve hidden this data.
It’s not about being secretive. That’s not our point. It’s about reducing dependencies between different parts of the application (that a change in one place won’t cascade down and require multiple changes elsewhere).
What is Inheritance?
This next idea of “Inheritance” is a great form of code reuse. Let’s say you start off by defining in your application a “Person” Class with a few attributes (name, address and phone number) and some simple behaviour. Later on, you figure out your application will need another Class and this one is called “Customer” but you realize that this new “Customer” Class is exactly the same as the “Person” Class with the difference that it has a “customerNumber”. You don’t want to add that “customerNumber” to your “Person” Class because we want to use Abstraction (not all of your “Person” objects will be customers).
You could do this by creating a completely separate Class but a better way is that we’ll create a new Class called “Customer” and, then, we say: “We are going to inherit from the “Person” Class”. That means our new “Customer” Class has everything that the “Person” Class has (all its attributes and behaviours) without us having to write any code and we just say in our “Customer” Class what we want to add to it. In this case, we would add a “customerNumber” or another new attribute or add a new method.
The term that’s most commonly used for this relationship is that the “Person” Class is the “Superclass” whereas the new “Customer” Class is called the “Subclass” but you can also hear this described as the “Parent Class” and the “Child Class”.
What is Polymorphism?
Finally, we have Polymorphism (which means “many forms”). It’s the most complex of the four terms but very powerful. It lets us automatically do the correct behaviour even if what we’re working with could take one of many different forms.
In a lot of languages, if we’re adding two variables together with the plus sign, if these variables are integers, it will numerically add them but, on the other hand, if the variables “a” and “b” are strings, what’ll happen is that it will concatenate them. It will automatically do the correct behaviour but a different behaviour when what we’ve given it could have one of many different forms. This example is built into a lot of languages but we can use the same idea with our own Classes and our own objects.
Here’s a practical example: Let’s say we define a “BankAccount” Class for a financial application and it describes attributes like:
- An “accountName”.
- A “balance”.
- A “deposit()” method.
- A “withdraw()” method.
We can then create more specialized Subclasses that inherit from it (like a “SavingsAccount” Class…A “CheckingAccount” Class…An “InvestmentAccount” Class…). So, they’re all inheriting. They all share the basic definition but let’s take it further. The rule says that, if you withdraw from an investment account, you should get a penalty if it’s not 30 days notice. So, we now have a bit more complex behaviour. Now, that “withdraw()” behaviour was originally defined in the “BankAccount” Class. So, I’m already inheriting it but I can provide a more specialized version of that just for the “InvestmentAccount” Class and this is referred to as “overriding” the method of the Superclass and that just means I write it again. So, I’m inheriting when useful and I can override behaviours when necessary.
That’s all for my introduction to OOP concepts, folks. Feel free to leave a comment below and stay tuned for more useful programming input here at the Oktara Software blog. See you next time and happy coding.