Principles of Object Oriented Programming — Part Four: Abstraction

The Inquisitive Dev
5 min readNov 2, 2020

--

This article is part of a series:

Part One: Encapsulation

Part Two: Inheritance

Part Three: Polymorphism

Part Four: Abstraction

In this series I am covering the the principles of object oriented programming. Last time I wrote about polymorphism, whereby multiple class methods can co-exist with the same name but different underlying logic. In the final installment of this series, I’m going to talk about abstraction.

This article was first published on:

Abstraction is a generic term, which basically means the reduction of complexity by removing unnecessary details. It can be used to describe many things we might come across in the real world. Take for example, driving a car. I don’t have the foggiest idea as to how applying pressure to the accelerator pedal causes the vehicle to move forward. Thankfully, I don’t need to know in order to drive my car. That detail has been abstracted away from me.

What is abstraction in programming?

Even basic software programs may have large, complex classes interacting with each other in various ways. As developers, we can manage this complexity in the application by removing (or abstracting away) the unnecessary details in a particular interaction.

Types of abstraction

As with the previous articles in this series I will be using Java in my examples. In Java, abstraction is achieved in two ways. Abstract classes and interfaces.

Abstract Classes

Abstract classes cannot be instantiated. Instead, an abstract class acts like a blueprint for other classes that subclass it. To make a class abstract, you need to add the ‘abstract’ keyword to the class signature and multiple classes can inherit common functionality from it. By default, methods declared in an abstract class will have their implementation defined, meaning they will have a method body. Adding the ‘abstract’ keyword to the method signature, allows the method to be declared without an implementation. Such methods will rely on the subclass to define their logic.

The example below demonstrates an abstract class called Shape being inherited from by a Square and a Circle subclass. Both of these subclasses provide the implementation for the Shape classes abstract methods.

// Console Output

Shape constructor called
Square constructor called
Shape constructor called
Circle constructor called
Square colour is green, its sides are all 4.0 in length and its areas is: 16.0
Get colour method overridden in Square subclass
Circle colour is blue, its radius is 3.0 and its areas is: 28.274333882308138
blue

Interfaces

Like abstract classes, interfaces cannot be instantiated directly. Interfaces are a way to group a set of related methods or functionalities together. They are declared using the ‘interface’ keyword. By default, methods declared in an interface will not have any implementation details, i.e. no body. If you add the ‘default’ keyword to the method signature (Java 8 onwards), you may define an implementation. Any classes implementing the interface must define the bodies for all methods not marked with the ‘default’ keyword.

The example below demonstrates a Car class implementing a Vehicle interface. In order to use the interface, the Car class must provide the implementation details of the abstract methods. The interface also makes use of the default keyword, allowing the implementation of the soundHorn method to be defined.

// Console Output

Gear: 0
Speed: 0
Speeding up by: 30
Changing to gear: 3
Slowing down by: 5
Gear: 3
Speed: 25
beep!

Why use an interface?

Interfaces let the developer add new functionality to a class without having to change the existing code. This means we can be more flexible and responsive to changes in infrastructure and requirements. However, an interface should be as simple as possible and not add unnecessary complexity. If you could achieve the same functionality with a conditional, where the various branches call different implementing methods, you might be better off doing that. Furthermore, an interface should also only be responsible for performing a single task. Do not try and get your interfaces to do too much.

A well designed interface should completely encapsulate a single concern. In other words the interface should perform a single task entirely and not rely on client code (the calling code) to fulfil its purpose. If the functionality is abstracted properly, the client code should work regardless of the implementation provided. For example, if the client code wants to save some data to a database it might call on an interface to include that functionality. If the database connection is unavailable for any reason, the implementation of the interface methods should handle the error appropriately. This might mean displaying an error message to the user or trying the connection again. The error should not ‘escape’ into the client code, where it could cause an uncaught exception.

Abstract Classes vs Interfaces in Java

Advantages of Abstraction

Abstraction allows for Polymorphism

Both abstract classes and interfaces allow for Polymorphism. Objects of a child class can be referred to using their parent class. Methods called on the parent bind to the child’s implementation.

Abstract enhances maintainability, flexibility, Scalability

Abstraction is a way to arrange code by breaking down large and complex functionality into smaller, more manageable and maintainable components. Imagine your job as a developer is maintain and add new features to an application. Which way would you rather work?

Option 1: Have all the functionality contained within one or two objects. Any new functionality would need to be ‘stitched’ into the existing code codebase, resulting in complex, long, inflexible and unscalable code.

Option 2: Have an application built from many smaller, loosely coupled components that can be swapped and upgraded independently of each other. Implementation logic can be changed or added to a single component without the need to change everything that interacts with it.

Clearly, option 2 is a no-brainer.

Abstraction focuses on Business Logic

Suppressing unnecessary details not only enhances the readability of code, it also simplifies the relationships between objects. As long as the object being called upon implements the public methods it exposes, it is irrelevant to other objects how this is achieved. By abstracting away the underlying technical implementation, the business logic becomes the focus of any interactions.

Abstraction vs Encapsulation

Sometimes encapsulation and abstraction can be confused. As described above, abstraction means only exposing that which is needed in the system/interaction of objects and hiding all unnecessary details. It also involves the extraction of common functionality into a single entity, where it can be utilised by multiple implementing classes.

Encapsulation is the principle of hiding data in a single entity or unit along with a method to protect information from outside. This makes the code more robust and predictable.

Subscribe

That concludes this mini-series on the principles of object oriented programming. If you found any of this useful I’d love you to become a subscriber to my blog. I will be dropping articles regularly on all things coding. Knowing I have people reading would mean the world. Head over to my site and hit subscribe.

As always, thanks for reading!

--

--