An abstract class is declared with the abstract keyword. It cannot be instantiated. It may contain:
- abstract methods: declared without a body; every concrete subclass must implement them;
- concrete methods, attributes and constructors.
abstract class Employee {
protected String name;
Employee(String name) { this.name = name; }
abstract double calculateSalary(); // no body
void display() { // concrete method
System.out.println(name + " earns " + calculateSalary());
}
}
class FullTime extends Employee {
double monthly;
FullTime(String name, double monthly) { super(name); this.monthly = monthly; }
@Override double calculateSalary() { return monthly; }
}
class PartTime extends Employee {
int hours; double rate;
PartTime(String name, int hours, double rate) { super(name); this.hours = hours; this.rate = rate; }
@Override double calculateSalary() { return hours * rate; }
}
// Employee e = new Employee("x"); // ERROR: abstract class
Employee e = new PartTime("Sunil", 40, 500);
e.display();Use an abstract class when subclasses are closely related and share some code (a common base) but must each fill in specific behaviour.
Rules for abstract classes
- An abstract class is declared with
abstract class Name. You cannot writenew Name(...). - An abstract method has
abstractand ends with a semicolon instead of a body:abstract double calculateSalary();. - If a class contains even one abstract method, the class itself must be declared abstract.
- A subclass must either implement every abstract method, or be declared abstract itself.
- An abstract class can have constructors, attributes, concrete methods and static members, just like any class. Its constructors run when a subclass object is created, through
super(...). - An abstract method cannot be
private,staticorfinal, because all three would stop a subclass from overriding it.
Walking through the Employee example
Employeecontains what every employee shares: aname, a constructor that sets it, and adisplay()method.- It cannot know how to calculate a salary, because full-time and part-time staff are paid differently, so
calculateSalary()is abstract. display()is concrete, but it calls the abstract method. Whene.display()runs for a PartTime object,calculateSalary()runs PartTime's version: 40 × 500 = 20000. The output isSunil earns 20000.0.
This pattern, where a general method in the parent calls steps that the children fill in, is called the template method pattern. The parent fixes the outline and the children supply the details.
Abstract types as references
You cannot create an Employee, but you can have Employee variables, arrays and parameters:
Employee[] staff = {
new FullTime("Kamala", 85000),
new PartTime("Sunil", 40, 500)
};
double payroll = 0;
for (Employee e : staff) payroll += e.calculateSalary();
System.out.println(payroll); // 105000.0This is polymorphism again, and now it is safe: the compiler guarantees that every kind of Employee has a real calculateSalary().
Common mistake: forgetting to implement one of the abstract methods in a subclass. The compiler reports PartTime is not abstract and does not override abstract method calculateSalary() in Employee. Either add the method, or mark the subclass abstract too.
Remember
- Abstract class: cannot be instantiated; it shares code and leaves some methods for the subclasses to complete.
- An abstract method has no body; concrete subclasses must override it.
- Use abstract types for variables, arrays and parameters.