Web Analytics

Abstract Classes

Intermediate ~30 min read

An abstract class is a class that cannot be instantiated directly. It's designed to be a base class that other classes extend. Abstract classes can contain both abstract methods (without implementation) and concrete methods (with implementation).

What is an Abstract Class?

An abstract class is declared with the abstract keyword. It represents an incomplete class that serves as a blueprint for subclasses.

abstract class Shape {
    String color;

    // Abstract method - no body, must be implemented by subclasses
    abstract double calculateArea();

    // Concrete method - has implementation
    void setColor(String color) {
        this.color = color;
    }
}
Key Characteristics:
  • Declared with abstract keyword
  • Cannot be instantiated (new Shape() is invalid)
  • Can have constructors (called by subclasses)
  • Can have both abstract and concrete methods
  • Can have instance variables

Abstract Methods

An abstract method has no body - just a declaration. Subclasses must provide an implementation.

abstract class Animal {
    // Abstract method - each animal sounds different
    abstract void makeSound();

    // Concrete method - all animals breathe the same way
    void breathe() {
        System.out.println("Breathing...");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {  // MUST implement abstract method
        System.out.println("Woof!");
    }
}

class Cat extends Animal {
    @Override
    void makeSound() {  // MUST implement abstract method
        System.out.println("Meow!");
    }
}
Rules for Abstract Methods:
  • No method body - ends with semicolon
  • Can only exist in abstract classes or interfaces
  • Cannot be final, static, or private
  • Subclasses must implement all abstract methods (or be abstract themselves)

Constructors in Abstract Classes

Abstract classes can have constructors. They are called when a subclass object is created.

abstract class Vehicle {
    String brand;
    int year;

    // Constructor in abstract class
    Vehicle(String brand, int year) {
        this.brand = brand;
        this.year = year;
        System.out.println("Vehicle constructor called");
    }

    abstract void start();
}

class Car extends Vehicle {
    int numDoors;

    Car(String brand, int year, int numDoors) {
        super(brand, year);  // Call abstract class constructor
        this.numDoors = numDoors;
        System.out.println("Car constructor called");
    }

    @Override
    void start() {
        System.out.println(brand + " car is starting");
    }
}

Concrete Methods in Abstract Classes

Abstract classes can provide default implementations that subclasses inherit or override:

abstract class Employee {
    String name;
    double baseSalary;

    Employee(String name, double baseSalary) {
        this.name = name;
        this.baseSalary = baseSalary;
    }

    // Abstract - different for each type
    abstract double calculateBonus();

    // Concrete - same for all employees
    double getTotalPay() {
        return baseSalary + calculateBonus();
    }

    // Concrete - can be overridden if needed
    void displayInfo() {
        System.out.println("Name: " + name);
        System.out.println("Total Pay: $" + getTotalPay());
    }
}
Output
Click Run to execute your code

When to Use Abstract Classes

  • Shared code among related classes: When subclasses share common code
  • Partial implementation: When you want to provide some default behavior but force subclasses to implement specific parts
  • Template method pattern: Define the skeleton of an algorithm, letting subclasses fill in the details
  • Access modifiers needed: When you need non-public methods (interfaces are implicitly public)
  • Instance variables: When you need to share state among subclasses

Abstract Class vs Interface

Abstract Class Interface
Can have instance variables Only constants (public static final)
Can have constructors Cannot have constructors
Single inheritance only Multiple implementation allowed
Any access modifier for methods Methods are public by default
Use for IS-A relationship with shared code Use for CAN-DO capability/behavior
Rule of Thumb: Use abstract classes when classes share code and state. Use interfaces when classes share behavior but not implementation.

Common Mistakes

  • Trying to instantiate an abstract class: new Animal() is a compile error
  • Forgetting to implement all abstract methods: Subclass must implement ALL abstract methods or be declared abstract itself
  • Making abstract methods private: Abstract methods must be accessible to subclasses
  • Overusing abstract classes: Consider interfaces for defining capabilities

Summary

  • Abstract classes cannot be instantiated directly
  • Abstract methods have no body and must be implemented by subclasses
  • Abstract classes can have constructors, instance variables, and concrete methods
  • Use abstract classes when you have shared code among related classes
  • A class that doesn't implement all abstract methods must itself be abstract