We use abstract classes to implement abstraction in Java. It is one of the key ideas to enable a higher level of abstraction in our code, hide implementation details, enforce polymorphism and promote code reusability.
In Java, abstract classes are similar to regular classes, but they are declared using the abstract keyword and cannot be instantiated. So what is the purpose of an abstract class if it can not be instantiated? Here is an idea: We mostly use an abstract class as a base class for other classes. It provides a set of common attributes and behaviours that the subclasses can inherit and specialize based on their specific requirements.
public abstract class AbstractClass {
// Fields (if any)
// Constructors (if any)
// Abstract Methods
public abstract void abstractMethod1();
public abstract void abstractMethod2();
// Non-Abstract Methods
public void concreteMethod() {
// Implementation
}
// Other methods (if any)
}
Now, one critical question still remains: Why can't an abstract class be instantiated? The idea is: It is often incomplete on its own, mainly because of the presence of abstract methods. Therefore, due to this incomplete or undefined behaviour, attempting to create an instance of the abstract class would not make sense.
abstract class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
// Abstract method: No implementation provided
public abstract void makeSound();
public void sleep() {
System.out.println(getName() + " is sleeping.");
}
public void eat() {
System.out.println(getName() + " is eating.");
}
// Getter method to retrieve the name of the animal
public String getName() {
return name;
}
}
class Dog extends Animal {
public Dog(String name) {
super(name);
}
// Implementing the abstract method from the superclass
@Override
public void makeSound() {
System.out.println("Woof woof!");
}
@Override
public void sleep() {
System.out.println("The dog named " + getName() + " is sleeping.");
}
}
class Cat extends Animal {
public Cat(String name) {
super(name);
}
// Implementing the abstract method from the superclass
@Override
public void makeSound() {
System.out.println("Meow meow!");
}
@Override
public void sleep() {
System.out.println("The cat named " + getName() + " is sleeping.");
}
}
public class Main {
public static void main(String[] args) {
// Instantiating Cat using Animal reference
Animal cat = new Cat("Whiskers");
// Calling the overridden makeSound() method of Cat
cat.makeSound();
// Calling the overridden sleep() method of Cat
cat.sleep();
// Calling the inherited eat() method from Animal
cat.eat();
// Instantiating Dog using Animal reference
Animal dog = new Dog("Buddy");
// Calling the overridden makeSound() method of Dog
dog.makeSound();
// Calling the overridden sleep() method of Dog
dog.sleep();
// Calling the inherited eat() method from Animal
dog.eat();
}
}
Let's understand the different concepts used in the above code.
As mentioned above, an abstract method is a method declared in an abstract class that does not have any implementation. It only provides the method signature (name, parameters, and return type) and a contract for the subclasses to implement. Note: Methods declared inside an interface are by default abstract.
abstract class Shape {
public abstract double calculateArea();
public abstract double calculatePerimeter();
}
class Square extends Shape {
private double side;
public Square(double side) {
this.side = side;
}
public double calculateArea() {
return side * side;
}
public double calculatePerimeter() {
return 4 * side;
}
}
public class Main {
public static void main(String[] args) {
Shape square = new Square(5);
double area = square.calculateArea();
double perimeter = square.calculatePerimeter();
System.out.println("Square area: " + area);
System.out.println("Square perimeter: " + perimeter);
}
}
A class containing one or more abstract methods must also be declared abstract. On the other hand, an abstract class may or may not contain abstract methods.
abstract class Vehicle {
public void start() {
System.out.println("Vehicle started.");
}
public void stop() {
System.out.println("Vehicle stopped.");
}
}
class Car extends Vehicle {
// Additional Car-specific methods and fields
}
We use abstract methods to enforce certain behaviours in subclasses. So, failure to implement an abstract method in a subclass will result in a compilation error.
For example, when you compile the following code, you will encounter a compilation error because the Square class is attempting to inherit from the Shape abstract class but has not implemented the abstract method calculatePerimeter().
abstract class Shape {
public abstract double calculateArea();
public abstract double calculatePerimeter();
}
class Square extends Shape {
private double side;
public Square(double side) {
this.side = side;
}
public double calculateArea() {
return side * side;
}
}
public class Main {
public static void main(String[] args) {
Shape square = new Square(5);
// Compilation error: Square is not abstract and does not override abstract method calculatePerimeter() in Shape
double area = square.calculateArea();
double perimeter = square.calculatePerimeter();
System.out.println("Square area: " + area);
System.out.println("Square perimeter: " + perimeter);
}
}
To make the above code work, we either need to override all the abstract methods of the abstract class or, make the subclass abstract.
For example, In the following code, we made the Square class abstract because the calculatePerimeter() method is not implemented in the Square class.
abstract class Shape {
public abstract double calculateArea();
public abstract double calculatePerimeter();
}
abstract class Square extends Shape {
private double side;
public Square(double side) {
this.side = side;
}
public double calculateArea() {
return side * side;
}
// calculatePerimeter() method not implementated
}
Note: If there is a need to extend a class with additional behaviour from multiple sources, the use of interfaces or composition might be more appropriate.
Thanks to Ankit Nishad for his contribution in creating the first version of this content. If you have any queries or feedback, please write us at contact@enjoyalgorithms.com. Enjoy learning, enjoy OOPS!