All 15 Interfaces & Abstract Classes questions
More in Interfaces & Abstract Classes
Advertisement
Java › Interfaces & Abstract Classes

How would you use an abstract class's constructor to enforce that certain validation or initialization logic always runs for every subclass, something an interface (lacking constructors entirely) cannot provide?

Intermediate

Answer

Since interfaces cannot have constructors at all, any initialization or validation logic needing to run whenever ANY implementing type is created can only be guaranteed via an abstract class's constructor, which every subclass's own constructor must implicitly or explicitly invoke (via super(...)) before completing its own construction -- this gives an abstract class a genuine structural guarantee (enforced by the compiler itself, since a subclass constructor literally cannot skip calling some form of its superclass's constructor) that shared validation always executes, a capability interfaces fundamentally cannot replicate no matter how default/static methods are used.
public abstract class Account {
    protected final double balance;
    protected Account(double initialBalance) {
        if (initialBalance < 0) {
            throw new IllegalArgumentException("Initial balance cannot be negative");
        }
        this.balance = initialBalance;
    }
}

public class SavingsAccount extends Account {
    public SavingsAccount(double initialBalance) {
        super(initialBalance);  // MUST call this, guaranteeing the validation always runs
    }
}
Real-world example A banking domain model's abstract Account class validates that no subclass (SavingsAccount, CheckingAccount, or any future account type) can ever be constructed with a negative initial balance, a guarantee enforced structurally through the constructor mechanism itself rather than relying on each subclass remembering to independently perform the same validation.

Common follow-ups: What happens if a subclass's constructor doesn't explicitly call super(...) -- does the abstract class's constructor still run?;How would you achieve a similar (though weaker, convention-based rather than compiler-enforced) guarantee using only interfaces and default methods?