Java OOPs Simplified - Part 5

Java OOPs Simplified - Part 5

ABSTRACTION

In the previous articles, we delve deep into the 2 pillars of OOPs, i.e. Inheritance and Polymorphism. In this, we will understand the important things related to another important pillar of OOPs, i.e. Abstraction. So the first question is;

What's meant by Abstraction in Java?

It is a concept in OOPs, that allows us to hide the complex implementation and show only the essential features of an object or class.

Now if you read this, and go for a real-time example, you will get confused. In many places on the internet, we can see examples of Facebook or WhatsApp, and it says abstraction is like hiding the codes or implementation and just showing what is needed.

So, here there is a possibility that beginners may get confused, they may think that if abstraction is not there we may be able to see the backend codes of applications like Facebook or WhatsApp. But this is not that, abstraction has nothing to do with the end-users of these apps, instead, this is a concept to help the programmers to reduce code complexity and thereby improve the code readability.

Now let's look at a code-based example of Abstraction. Here I'm gonna show you what actually abstraction help us to achieve. We are going to see both the normal method implementation and abstract method implementation.

// NORMAL CLASS
class Animal {
    // Normal method with implementation
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a1 = new Animal(); 
        // Call the normal method
        a1.makeSound(); // Output: Dog barks
    }
}

The code provided above demonstrates the implementation of a normal class. In the Animal class, there is a method called makeSound() which has an implementation (means it actually explains what that function do, here it has a statement to print "Dog barks"). In the Main class, an instance a1 of the Animal class is created, and we call the makeSound() method using a1.makeSound().

Now let's have a look at the implementation of an abstract class.

// Abstract class
abstract class Animal {
    // Abstract method (no implementation)
    public abstract void makeSound();
}

// Concrete subclass
class Dog extends Animal {
    // Implementing the abstract method
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        // Create an instance of Dog
        Dog d1 = new Dog();

        // Call the abstract method
        d1.makeSound(); // Output: Dog barks
    }
}

"In the example provided above, the Animal class is declared as abstract using the abstract keyword. Inside the abstract class, you can observe the presence of an abstract method, makeSound().

Since this method is abstract, it lacks a direct implementation. It is merely declared without a concrete implementation (without any body). This demonstrates the concept of hiding the code implementation, as mentioned earlier.

In the code, a normal class named Dog is created, and the makeSound() method is implemented within it. It's because, you cannot create an instance of an abstract class directly, which means that Animal a1 = new Animal() is not possible.

Instead, we extend a normal class to create a subclass, as shown in the above program. You can see that in the code, an instance of the Dog class is created using Dog d1 = new Dog(). This instance is then used to call the makeSound() method."

Advantages of Abstraction

  1. It improves code readability.

  2. It hides the code complexity, by declaring methods as abstract.

  3. It supports code reusability, as multiple classes can implement the same interface or extend the same abstract class.

  4. It simplifies the code by breaking it into smaller and manageable parts.

Now, we have an idea about the concept of Abstraction in OOPs, now lets have a close look at the Abstract methods.

What is an Abstract Method?

Now we have an idea about abstract class as we have gone through the concept of abstraction. So, abstract method is a method which is declared in a class, but it doesn't have any instructions or details on how it should work, so in short, a method without a body.

It doesn't have an implementation, it only contains the method declaration.

It is also important to note that you have to use the keyword abstract before any abstract method.

NB: When you have an abstract method in a class, you can't create an object directly from that class. You have to create a new class that "extends" the abstract class(subclass) and provides the implementation of your abstract method in that new class(subclass).

So let's see how to create an abstract method as per above instructions;

abstract class Cars {
    // Abstract method without implementation
    abstract void Ferrrari();

    // Regular method with an implementation
    void Audi() {
        System.out.println("This is an Audi car");
    }
}

Now if you want to implement this we have to create a subclass extending the main class called Cars . Let's see how to implement this abstract class called Ferrari .

class SUV extends Cars {
    // Implementation of the abstract method
    void Ferrari() {
        System.out.println("This is the red Ferrari");
    }
}

So here we have created a subclass called SUV and implemented the abstract method Ferrari() . So this is how we implement an abstract method.

Now if you want to create more subclasses and implement the method, you can do that. So let's create another subclass Sedan and implement the same abstract method Ferrari() .

class Sedan extends Cars {
    // Implementation of the abstract method
    void Ferrari() {
        System.out.println("This is the New Sedan model of Ferrari");
    }
}

Let's have a look at the implementation of this.

public class Main {
    public static void main(String[] args) {
        // Creating objects of the concrete classes
        SUV theSuv = new SUV();
        Sedan theSedan = new Sedan();

        // Calling the abstract method and the regular method
        theSuv.Ferrari();  // Output: This is the red Ferrari
        theSuv.Audi();      // Output: This is an Audi car.

        theSedan.Ferrari();  // Output: This is the New Sedan model of Ferrari
        theSedan.Audi();      // Output: This is an Audi car
    }
}

In the Main class, objects of both SUV and Sedan are created and used to call both the abstract method and the regular method.

How to achieve Abstraction in Java?

There are mainly 2 ways to achieve abstraction in Java;

  1. using Abstract Class(0 to 100% abstraction).

  2. using Interfaces.

You already saw how can we achieve abstraction using an abstract class. So the main things to be noted while creating an abstract class is that you have to use an abstract keyword. You can use both abstract and non-abstract methods in an abstract class. It cannot be instantiated. Also you need to extend a subclass for implementing an abstract method in an abstract class.

So now let's see how to achieve abstraction using Interfaces.

Abstraction using Interfaces

What is an interface?

In simple words we can say its a set of rules. It's more like an agreement, that is if you want to be part of that agreement you must be ready to follow the set of rules provided in the agreement.

In interfaces, all the methods are abstract by default which means in interface we can only declare the methods, there will be no definitions or implementations for that method within the interface.

interface Vehicle {
    void drive();  // Just says: "Hey, you must have a drive() method!"
}

So the next question is, then how will we implement these abstract methods in interfaces?

So, for implementing the methods in an interface, we need to define a class using the keyword 'implements' and then implement those methods which we declare in the interfaces inside that class.


interface Vehicle {
    void drive();  
}

class Road implements Vehicles {
    // We HAVE to provide the implementation for draw() because we said we implement Drawable
    public void drive() {
        System.out.println("Always Drive Carefully");
    }
}

So, this is how we use interfaces to implement abstraction. You can take the example of implementing multiple inheritances in Java as an illustration of interfaces using the concept of abstraction to achieve multiple inheritance in Java.

Is it necessary to have at least one abstract method in an Abstract Class?

No, its is not necessary that an abstract class should contain at least one abstract method. An abstract class can exist without any abstract methods. Abstract classes can also contain concrete methods (methods with a complete implementation), fields, and constructors.

An abstract class provides 0% to 100% abstraction, which means that it can either contain only non-abstract methods (concrete methods), resulting in 0% abstraction, or it can consist entirely of abstract methods, achieving 100% abstraction. It is also possible for an abstract class to contain both abstract and non-abstract methods simultaneously.