Abstract class

The abstract class helps to achieve an Object-oriented concept of abstraction. Abstraction means showing the high-level details and hiding the low-level details.

Day to day life examples :

a ) When we are using a keyboard, we click buttons and it reflects on the screen. Many of us are not aware of how this process works in the background.

b ) We are driving our car daily but what all details do we know about it? We know how to use the steering, how to use brakes, clutch, etc. But we don’t know what happens in the background when we apply a brake?

So these are examples of abstraction, we just know about the top-level details, and the underlined details are hidden. It does not follow a strict abstraction like the interface because it consists of abstract methods as well as non-abstract methods.

abstract methods: Don’t contain the method definition.
non-abstract methods: Contain method definition.

When to use an abstract class?

1 ) When we don’t want to instantiate a class.

abstract class Car {
  void wheels() {
    System.out.println("Car is a 4 wheeler vehicle");
  }
}

public class Demo {
  public static void main(String[] args) {
    Car car = new Car();
  }
}

CE : Cannot instantiate the type Car

2 ) When we don’t know the definition of methods.

abstract class Car {
  abstract String manufacturerName();
  abstract String modelName();
  abstract void topSpeed();
  void wheels() {
    System.out.println("Car is a 4 wheeler vehicle");
  }
}

Different Car manufacturers will have different car models and specifications, but the wheels will be a common functionality as all the cars will be having 4 wheels. So we are defining the wheels as a non-abstract method ( as we are sure about the implementation ) and the rest as abstract methods.

How to make use of abstract methods?

We have to implement the abstract methods of an abstract class. Hence we will create a Sub-class to implement those methods. We have to make use of the “extends” keyword to implement an abstract class.

class LamborghiniCar extends Car {
  @Override
  public String manufacturerName() {
    return "Automobili Lamborghini";
  }

  @Override
  public String modelName() {
    return "Lamborghini Aventador";
  }

  @Override
  public void topSpeed() {
    System.out.println("0 to 60 in 2.9 secs");
  }
}

Does java support multiple inheritance using classes?

No, it don’t. It is an ambiguity/confusion, let us try to understand it with an example :

abstract class Car {
  void wheels() {
    System.out.println("Car is a 4 wheeler vehicle");
  }
}

abstract class Bike {
  void wheels() {
    System.out.println("Bike is a 2 wheeler vehicle");
  }
}

public class Vehicle extends Car, Bike {
  public static void main(String[] args) {
    Vehicle vehicle = new Vehicle();
    vehicle.wheels();
  }
}

Vehicle class has extended both the Car and Bike class , both the classes are having wheels method . So our Vehicle class will get confused on which wheels method to be used hence the above code cannot be compiled .

How does java support multiple inheritance using the interface?

Java classes can implement more than one interface because they do not cause any ambiguity. Let’s try to understand :

interface Car {
  void wheels();
}

interface Bike {
  void wheels();
}

class Vehicle implements Car, Bike {
  @Override
  public void wheels() {
    System.out.println("Car has 4 wheels whereas Bike has 2");
  }
}

public class Demo {
  public static void main(String[] args) {
    Vehicle vehicle = new Vehicle();
    vehicle.wheels();
  }
}

Output : Car has 4 wheels whereas Bike has 2

As interfaces before java 8 are having only abstract methods , Our sub-class won't be confused as no method was implemented before and sub-class will happily implement only a single method .

The abstract class just unlike the interface has Constructors too, Why is it so?

The constructor’s main purpose is to initialize the variables of a class and an abstract class can have private variables hence we need a constructor to initialize them. Constructor is called when an instance of the subclass is created or it can be called using a super keyword.

abstract class Cars {
  private int wheels;
  int seats;
  Cars() {
    System.out.println("Car constructor");
  }

  Cars(int wheels) {
    this.wheels = wheels;
  }

  int getWheels() {
    return wheels;
  }
}

class BMWCar extends Cars {
  String modelName;
  BMWCar(int wheels, String modelName, int seats) {
    super(wheels);
    this.modelName = modelName;
    this.seats = seats;
  }
}

public class Demo {
  public static void main(String[] args) {
    BMWCar bmwCar = new BMWCar(4, "Bayerische Motoren Werke", 2);
    System.out.println("No. of wheels : " + bmwCar.getWheels());
    System.out.println("No. of seats : " + bmwCar.seats);
  }
}

Can an abstract class be final?

No. If a class is abstract then it means we have to implement the class. If we use a final keyword with the class it means we cannot inherit that class. So final with abstract is an illegal combination.

Can an abstract class/method be static?

If a class is static it means all the methods within that class are static. If the abstract methods are static then we cannot override those methods. Static methods are overhidden by default.

static abstract class Cars {
  abstract void getWheels();
}
CE : Illegal modifier for the class Cars; only public, abstract & final are permitted

abstract class Cars {
  abstract static void getWheels();
}
CE : The abstract method getWheels in type Cars can only set a visibility modifier, one of public or protected .

Types of variables in abstract class :

1 ) final 2 ) Non-final 3 ) static 4 ) Non-static 5 ) private 6 ) protected

private: As an abstract class has a constructor, so we can initialize the private variables using constructors.

protected: We can access them only in the sub-class.

Non-final / Non-static: We can access the variables and update the state of those variables in the sub-class.

Static & Non-final Variables :

abstract class Cars {
  static int wheels = 4;
  int getWheels() {
    return wheels;
  }
  abstract void updateWheels();
}

class LamborghiniCar extends Cars {
  void updateWheels() {
    wheels = 6;
  }
}

class BMWCar extends Cars {
  void updateWheels() {
    // Doing nothing here 
  }
}

public class Demo {
  public static void main(String[] args) {
    Cars lamborghiniCar = new LamborghiniCar();
    lamborghiniCar.updateWheels();
    System.out.println(" LamborghiniCar Updated wheels: " + lamborghiniCar.getWheels());

    Cars bmwCar = new BMWCar();
    bmwCar.updateWheels();
    System.out.println(" BMWCar Updated wheels: " + bmwCar.getWheels());
  }
}

Output : LamborghiniCar Updated wheels: 6
         BMWCar Updated wheels: 6

Non-static & Non-final Variables :

abstract class Cars {
  int wheels = 4;
  int getWheels() {
    return wheels;
  }
  abstract void updateWheels();
}

class LamborghiniCar extends Cars {
  void updateWheels() {
    wheels = 6;
  }
}

class BMWCar extends Cars {
  void updateWheels() {
    // Doing nothing here 
  }
}
public class Demo {
  public static void main(String[] args) {
    Cars lamborghiniCar = new LamborghiniCar();
    lamborghiniCar.updateWheels();
    System.out.println(" LamborghiniCar Updated wheels: " + lamborghiniCar.getWheels());

    Cars bmwCar = new BMWCar();
    bmwCar.updateWheels();
    System.out.println(" BMWCar Updated wheels: " + bmwCar.getWheels());
  }
}

O/P : LamborghiniCar Updated wheels: 6
      BMWCar Updated wheels: 4

This is all about abstract class. If you like this article please share it. If you want to add anything extra please comment below and write to me if I have gone wrong anywhere.


Leave a Comment