What an abstract class is
Sometimes a family of classes shares a behavior, but each member does it differently. Every Animal can speak(), yet how it speaks depends on whether it is a dog or a cat. An abstract class captures the shared part and leaves the rest for subclasses to fill in. It is a half-finished template that you can't use on its own.
The syntax
Put the abstract keyword on the class, and on any method that has no body:
abstract class Animal {
public abstract void speak();
}
An abstract method has a signature followed by a semicolon instead of a body. It declares what every subclass must be able to do without saying how.
Two rules with teeth
- You can't create an abstract class with
new. Writingnew Animal()is a compile error:Animal is abstract; cannot be instantiated. You must create an object of a concrete subclass. - A concrete subclass must implement every abstract method. If it doesn't, the compiler refuses to compile it, with a message such as
Dog is not abstract and does not override abstract method speak() in Animal.
Together these make the abstract class a contract that the compiler enforces. Anyone holding an Animal knows it can speak, because no object of a half-finished class can ever exist.
Mixing abstract and concrete members
An abstract class may also contain ordinary methods with bodies, fields and constructors. Subclasses inherit them like any other members. Only the methods marked abstract must be overridden. This lets a template fix the common steps and leave one step open:
abstract class Shape {
public abstract double area();
public String describe() {
return "area " + area();
}
}
class Square extends Shape {
private double s;
public Square(double s) {
this.s = s;
}
@Override
public double area() {
return s * s;
}
}
With these definitions, new Square(3).describe() returns area 9.0. The concrete describe in Shape calls area(), and Java runs Square's version, because the object is a Square. This is the same dynamic dispatch as in the polymorphism lesson.
The lesson's exercise, step by step
The starter code defines the abstract Animal with one abstract method, and a mainFunction that creates a Dog and calls speak() on it. Dog does not exist yet. Two steps provide it:
- Declare the subclass. Below
Animal, writeclass Dog extends Animal. An abstract class can only be used through a concrete subclass, so this class is what makesAnimalusable. - Implement the method. Inside
Dog, writepublic void speak()with@Overrideand print"Woof". The method must bepublic, like the abstract one it replaces.
The finished program:
abstract class Animal {
public abstract void speak();
}
class Dog extends Animal {
@Override
public void speak() {
System.out.println("Woof");
}
}
class Solution {
public void mainFunction() {
Dog rex = new Dog();
rex.speak();
}
}
It prints:
Woof
Without the method body, Dog would fail to compile, since it would inherit an abstract method it never implemented. Without extends Animal, the contract wouldn't apply, and Dog would be an unrelated class.
Details worth knowing
- Abstract variables are fine. You can't write
new Animal(), but a variable of typeAnimalis allowed and can refer to any concrete subclass object:Animal pet = new Dog();. - Abstract methods have no body. Adding braces, as in
public abstract void speak() { }, is a compile error. - A class with an abstract method must be abstract. Declaring an abstract method inside a normal class doesn't compile.
- An abstract class can have no abstract methods. That is legal. It simply cannot be instantiated.
- Subclasses can stay abstract. A subclass that implements only some of the abstract methods must itself be declared
abstract. - Abstract and private don't mix. An abstract method is meant to be overridden, so it can't be
private,finalorstatic. - Interfaces are a related tool. A class extends only one parent but may implement several interfaces. Abstract classes are best when subclasses share fields or code.
Common mistakes
- Instantiating the abstract class.
new Animal()never compiles, whatever the arguments. - Forgetting to implement the method. Every concrete subclass needs a body for every abstract method it inherits.
- Getting the signature wrong.
public void speak(int times)is a different method and doesn't implementspeak(). With@Overridethe compiler reports the mistake. - Narrowing access. Writing
void speak()withoutpublicinDogis an error, because an override can't be less visible than the method it replaces. - Forgetting
extends. A class with the right method but noextends Animaldoesn't count as an animal.
Key takeaways
- An abstract class is a template you can't instantiate directly.
- An abstract method has no body, and every concrete subclass must implement it.
- Abstract classes can also hold fields and ordinary methods that subclasses inherit.
- Variables may have the abstract type and hold subclass objects, so polymorphism still works.
- The compiler enforces the contract: missing implementations are compile errors, not runtime surprises.