Abstract Classes and Abstract Methods

Naveen AnamaneniUpdated · 6 min read

Every employee gets a payslip with the same layout: name, employee id, pay for the month. Only the pay calculation differs: full-time staff get a fixed salary, contractors are paid by the hour. An abstract class lets you write the shared part once (the payslip layout) and leave a blank (the pay calculation) that every subclass must fill in. You can't create an object of the abstract class itself, because it isn't finished.

A Class with a Blank

Shared code once; the blank is filled by each subclass
Payslips.java▶ Try it
public class Payslips {
    abstract static class Employee {
        private final String name;
        private final String id;
 
        Employee(String name, String id) {
            this.name = name;
            this.id = id;
        }
 
        abstract long monthlyPay();
 
        String payslip() {
            return id + " " + name + ": Rs. " + monthlyPay();
        }
    }
 
    static class FullTimeEmployee extends Employee {
        private final long salary;
 
        FullTimeEmployee(String name, String id, long salary) {
            super(name, id);
            this.salary = salary;
        }
 
        @Override
        long monthlyPay() { return salary; }
    }
 
    static class Contractor extends Employee {
        private final int hours;
        private final long ratePerHour;
 
        Contractor(String name, String id, int hours, long ratePerHour) {
            super(name, id);
            this.hours = hours;
            this.ratePerHour = ratePerHour;
        }
 
        @Override
        long monthlyPay() { return hours * ratePerHour; }
    }
 
    public static void main(String[] args) {
        Employee[] staff = {
            new FullTimeEmployee("Navika", "E101", 85000),
            new Contractor("Advitha", "C207", 120, 600)
        };
        for (Employee e : staff) {
            System.out.println(e.payslip());
        }
    }
}
Output
E101 Navika: Rs. 85000
C207 Advitha: Rs. 72000

How it works

  1. abstract class Employee can have fields, a constructor and finished methods, just like a normal class.
  2. abstract long monthlyPay(); has no body, only a semicolon. It's a blank that subclasses must fill.
  3. payslip() is finished code that calls the blank. At runtime, the subclass's monthlyPay() runs: 120 × 600 = 72,000 for Advitha.
  4. The Employee constructor still runs, through super(name, id), to set up the shared fields.

Try it yourself: add an Intern subclass with a fixed stipend of Rs. 15,000, and add Srihitha as an intern.

The Rules

RuleDetail
Can't use new on itnew Employee(...) is a compile error
Can have constructorsThey run when a subclass object is created
Can have fields, static members and finished methodsLike any class
Can have zero abstract methodsStill can't be instantiated; useful for a "base only" class
An abstract method has no bodyabstract long monthlyPay();
A class with an abstract method must be abstractOtherwise it's a compile error
abstract can't combine with final, private or static on a methodEach would make the method impossible to override

Breaking the rules looks like this:

E1.java
abstract class Shape { abstract double area(); }
class Circle extends Shape { }
class Use { Shape s = new Shape(); }
abstract final class X {}
class Y { abstract void m(); }
Compiler output
E1.java:4: error: illegal combination of modifiers: abstract and final
abstract final class X {}
               ^
E1.java:2: error: Circle is not abstract and does not override abstract method area() in Shape
class Circle extends Shape { }
^
E1.java:3: error: Shape is abstract; cannot be instantiated
class Use { Shape s = new Shape(); }
                      ^
E1.java:5: error: Y is not abstract and does not override abstract method m() in Y
class Y { abstract void m(); }
^
4 errors

The Template Method Idea

payslip() above is a template method: the abstract class fixes the steps and the order, and subclasses supply one or more steps. The JDK uses it widely. java.util.AbstractList implements dozens of list methods on top of two abstract ones, get(int) and size(). Write those two and you have a working read-only list.

Common Mistakes

Trying to create the abstract class with new. Create a concrete subclass instead, or an anonymous class (see "Anonymous Inner Class in Java").

Forgetting one abstract method in a subclass. The error names the missing method; implement it or make the subclass abstract.

Calling an abstract method from the constructor. The subclass's fields aren't set yet when it runs, so it can see zeros and nulls.

Interview Corner

Can an abstract class have a constructor?

Yes. It can't be instantiated directly, but its constructor runs whenever a subclass object is created, through super(...), to initialize the fields the abstract class declares.

Can an abstract class have no abstract methods?

Yes. Declaring a class abstract only prevents direct instantiation. It's useful for base classes that should exist only as parents, such as java.util.AbstractList's helpers or framework base classes.

Why can't an abstract method be final, private or static?

An abstract method exists to be overridden. A final method can't be overridden, a private method isn't visible to subclasses, and a static method belongs to the class and isn't overridden, so each combination would make the method impossible to implement.

Practice

  1. Easy: Create an abstract class Shape with an abstract area() and a finished describe() that prints the area. Implement Circle and Square.
  2. Harder: Create an abstract class Report with a final print() that calls header(), body() and footer(). Make header() and footer() finished and body() abstract, then write SalesReport and StockReport.

Quick check: Abstract classes

4 questions
1What happens with new Employee(...) if Employee is abstract?
2Can an abstract class have a constructor?
3A concrete subclass skips one abstract method. Result?
4Which modifier can go with abstract on a method?

Key Takeaways

Was this tutorial helpful?

Lesson 133 of 482