🌱BeginnerObject-Oriented Programming
Abstract Classes
Define incomplete class templates with abstract methods that subclasses must implement, enforcing a shared contract.
Overview
An abstract class is a class that cannot be instantiated on its own - it exists only to be extended. It can contain regular (concrete) methods with implementations AND abstract methods that have no body and must be implemented by every concrete subclass.
Use abstract classes when you have shared behaviour to put in the parent, but part of the behaviour varies by subclass and the parent cannot provide a meaningful default.
Example: Shape is a good abstract class. All shapes have a colour and a name, but you can't meaningfully compute area() for "a generic shape" - each concrete shape (Circle, Square) must provide its own area().
Key Points
- •abstract class cannot be instantiated with new
- •abstract method has no body: `abstract double area();`
- •Every non-abstract subclass must implement all abstract methods
- •Abstract classes can have fields, constructors, and concrete methods
- •A subclass that does not implement all abstract methods must itself be abstract
- •Abstract classes are used for "template" designs where some steps are fixed and others vary
- •Use abstract classes for "is-a" with shared state/behaviour; use interfaces for capabilities (J039)
Examples
Abstract Shape class
abstract class Shape {
String colour;
Shape(String colour) {
this.colour = colour;
}
// Abstract - subclasses must provide implementation
abstract double area();
abstract double perimeter();
// Concrete - shared by all subclasses
void describe() {
System.out.printf("%s %s: area=%.2f, perimeter=%.2f%n",
colour, getClass().getSimpleName(), area(), perimeter());
}
}
class Circle extends Shape {
double radius;
Circle(String colour, double radius) {
super(colour);
this.radius = radius;
}
@Override
public double area() { return Math.PI * radius * radius; }
@Override
public double perimeter() { return 2 * Math.PI * radius; }
}
class Rectangle extends Shape {
int width, height;
Rectangle(String colour, int width, int height) {
super(colour);
this.width = width;
this.height = height;
}
@Override
public double area() { return width * height; }
@Override
public double perimeter() { return 2 * (width + height); }
}
public class Main {
public static void main(String[] args) {
Shape[] shapes = {
new Circle("red", 5),
new Rectangle("blue", 4, 6)
};
for (Shape s : shapes) {
s.describe();
}
// new Shape("green"); // compile error - abstract class can't be instantiated
}
}describe() calls area() and perimeter() - those calls go to the appropriate subclass implementation at runtime.
Abstract class with template method pattern
abstract class DataProcessor {
// Template method - defines the algorithm skeleton
final void process() {
readData();
processData();
writeResults();
}
abstract void readData();
abstract void processData();
// Concrete with default - subclasses can override if needed
void writeResults() {
System.out.println("Writing results to default output...");
}
}
class CsvProcessor extends DataProcessor {
@Override
void readData() { System.out.println("Reading CSV file..."); }
@Override
void processData() { System.out.println("Processing CSV rows..."); }
}
class JsonProcessor extends DataProcessor {
@Override
void readData() { System.out.println("Parsing JSON..."); }
@Override
void processData() { System.out.println("Processing JSON nodes..."); }
@Override
void writeResults() { System.out.println("Saving to JSON output..."); }
}
public class Main {
public static void main(String[] args) {
new CsvProcessor().process();
System.out.println("---");
new JsonProcessor().process();
}
}process() is final - subclasses can't change the overall algorithm, only the individual steps.
Common Mistakes
- Trying to instantiate an abstract class: `new Shape("red")` - compile error
- Forgetting to implement all abstract methods in a subclass - the subclass must also be declared abstract
- Mixing up abstract classes (partial implementation, can have fields) and interfaces (no fields, pure contract)
Note
Choose abstract class over interface when subclasses share state (fields) or common concrete method implementations. If you only need to define a contract with no shared state, use an interface (J039).
Exercises
Write Java code and click Run to execute it instantly. When your output looks correct, mark as done.
Loading editor…
Completed: 0 / 4 exercises
Knowledge Check
Question 1 of 4