2 min read

Abstract Classes in Java

Abstract classes are classes that provide code reuse as well as enforce what needs to be implemented.
Abstract Classes in Java

Abstract Classes

Abstract classes are like normal classes but with a few differences. They are used with class inheritance. Abstract classes are classes that do not have a full implementation. Abstract classes can be used to provide code that subclasses can reuse as well as declare methods that those subclasses are required to implement. Abstract classes are declared using the abstract keyword.

public abstract class Message {
    // ...
}

Abstract Methods

A big reason for using abstract classes is they can have abstract methods declared on them. Abstract methods in abstract classes are similar to a method defined on an interface. They define a method signature for a method that needs to be implemented when inheriting a class.

public abstract class Message {
    public abstract boolean isExpired();
}

This abstract class defines a single abstract method on it.

Abstract methods must be implemented in the class that inherits the abstract class unless that class is also abstract. If a non-abstract class doesn't implement all methods, it will result in a compiler error.

// Compiler Error:
//   Comment is not abstract and does not override 
//     abstract method isExpired() in Message.
public class Comment extends Message {
}

Since this class isn't marked as abstract, it results in a compiler error. To fix this, the Comment class would need to provide an implementation for the isExpired() method.

public class Comment extends Message {
    @Override
    public boolean isExpired() {
        return false;
    }
}

Abstract methods in abstract classes work the same as abstract methods in interfaces.

Controlling Instantiation

Abstract classes allow you to control instantiation. If you have an abstract class, it cannot be instantiated directly.

// Compiler Error:
//   Message is abstract; cannot be instantiated
final var message = new Message();

If you want to create an instance, you would first need a class to inherit Message.

public class Comment extends Message {
}

You can now create instances of the Comment class that inherits Message.

final var comment = new Comment();

This helps you build a class hierarchy and only instantiate classes that make sense to.

Anonymous Classes

Although you cannot instantiate an abstract class, you can create an implementation of it using an anonymous class and instantiate it that way.

public abstract class Message {
    private final String text;

    public Message(final String text) {
        this.text = text;
    }

    public String text() {
        return text;
    }

    public abstract boolean isExpired();
}

Using this class, you can create an anonymous implementation of it with the following:

final var message = new Message("Hello") {
    @Override
    public boolean isExpired() {
        return false;
    }
}

This allows you to provide the implementation of the abstract methods when the instance is created.

Conclusion

Abstract classes allow for code reuse and to provide partial implementations of a class. They allow you to control instantiation and also allow you to provide abstract methods that other subclasses must implement.