OOP: Abstraction in Java

Beknazar
5 min readMay 4, 2021

--

Abstraction focuses on what an object does instead of how it does it.

Abstraction allows us to focus on what an object does instead of how it does. We can achieve abstraction with abstract methods, we can create abstract methods in abstract classes and interfaces. When abstraction is used there is a contract between abstraction and its concrete classes that forces concrete classes to have specific behaviors driven from abstraction.

  1. Abstract class.
  2. Interface.

Abstract class

  • An abstract class is a special class in Java that can have abstract methods.
  • We cannot initialize abstract classes directly.
  • The abstract class can have regular methods and properties as well.
  • If an abstract class extends another abstract class but the implementation of abstract methods is not required.
  • The first non-abstract class that extends the abstract class must implement all its abstract methods.
  • The class can extend only one abstract class by the rules of inheritance to avoid the diamond problem.
public abstract class Vehicle{
public String name;

public abstract void drive();
public abstract void stop();
}

We have an abstract class Vehicle with two abstract methods move and stop. All vehicles should be able to move and stop but the way they do will be different and based on concrete class implementation.

public class Car extends Vehicle {

@Override
public void drive() {
System.out.println("Car is driving");
}

@Override
public void stop() {
System.out.println("Car is stopped");
}
}

In the above example, Car class is extending the Vehicle abstract class. The Car class is a concrete class and it must implement all abstract methods from Vehicle class. It’s kind of agreement for the Car class with the abstract class so if Car wants to be a Vehicle. It should have implemented the abstract methods of Vehicle.

We implement abstract methods by overriding them.

Overriding rules:

1. the method name should be same.

2. the number, order, and data type of argument should be same. Data type can be covariant as well.

3. access modifier should be same or more accessible.

4. if overriding method throws exception in the method declaration. Exception should be same or smaller(child exceptions) than parent’s class method or no exception at all.

Let’s have another concrete class

public class Motorcycle extends Vehicle {

@Override
public void drive() {
System.out.println("Motorcycle is driving");
}

@Override
public void stop() {
System.out.println("Motorcycle is stopped");
}
}

We have another class that extends our abstract Vehicle class and implements its abstract methods.

Why do we need to create abstract classes and then create regular classes that extend them? Why just don’t create two regular classes?

The code should be designed to make changes easier. There is one powerful OOP principle — code to the interface, not to concrete classes. When we say interface we are referring to abstraction. Let’s see an example

public class Main {
public static void main(String[] args) {
// we cannot assign abstract class directly
// Vehicle vehicle = new Vehicle();

Vehicle vehicle = new Car();
vehicle.drive();
// a lot of code here ...

vehicle.stop();
}
}

We cannot initialize abstract class directly so it’s not useful by itself and always needs to be used with concrete classes.

Let’s say we have a program that responsible to drive a vehicle to a specific destination. Now, business wants to add Motorcycle. If we wouldn’t use an abstract class and code them differently with different method names and overall differently. We had to write a new program for Motorcycle. Luckily we coded to abstraction and we can just change one line.

public class Main {
public static void main(String[] args) {
Vehicle vehicle = new Motorcycle();
vehicle.drive();
// a lot of code here ...

vehicle.stop();
}
}

Interface

  • The interface can have only abstract methods except for static and default methods.
  • We cannot initialize the interface directly.
  • All interface properties are public static final. Basically, they are all constants by default.
  • public static final is optional to type for properties. It will be injected by default.
  • public abstract is optional to type for methods in the interface. It will be injected by default.
  • We need to use implements keyword to implement our interface. One class can implement multiple interfaces.
  • static and default methods can have bodies in the interface.

Let’s see the same example as with abstract class

public interface Vehicle {
public static final String str;
// private String str1; does not compile
void drive(); // public abstract will be injected by default
void stop(); // public abstract will be injected by default
// static method can have a body
public static String setStr(String strInput) {
str = strInput;
}
// default method can have a body
public default void printStr() {
System.out.println(str);
}
}

Above we have our interface. I have added extra code to show you some details about the default public static final properties and two methods that can have bodies.

public class Car implements Vehicle {

@Override
public void drive() {
System.out.println("Car is driving");
}

@Override
public void stop() {
System.out.println("Car is stopped");
}
}

We created our first concrete class for our interface. We use implements keyword in order to implement our interface.

public class Motorcycle implements Vehicle {

@Override
public void drive() {
System.out.println("Motorcycle is driving");
}

@Override
public void stop() {
System.out.println("Motorcycle is stopped");
}
}

And another concreate class.

public class Main {
public static void main(String[] args) {
// we cannot assign interface directly
// Vehicle vehicle = new Vehicle();

Vehicle vehicle = new Car();
vehicle.drive();
// a lot of code here ...

vehicle.stop();
}
}

We cannot initialize interfaces directly so they are not useful at all without concrete classes.

That’s it about abstraction in Java. Have a good day!

--

--