Introduction
In object-oriented programming, abstraction refers to the practice of exposing only relevant details while hiding the complex implementation. In Java, developers achieve this abstraction through abstract classes and interfaces. While both promote abstraction, each serves a different purpose. This article focuses on abstract classes, explaining their structure, use cases, and how they compare to interfaces. For a comprehensive discussion on interfaces, see Interfaces in Java.
1. What Is an Abstract Class?
An abstract class in Java is a class declared with the abstract keyword. It may include abstract methods—those without an implementation—as well as fully defined methods. Abstract classes provide a partially complete blueprint, ensuring that subclasses implement specific behaviors.
“Abstract classes let you define some behaviors; they force your subclasses to provide others.” — Oracle Java Tutorial
2. Syntax
The following example shows how to declare an abstract class that includes both abstract and concrete methods. This balance enables enforcing a contract while sharing common behavior.
public abstract class Vehicle {
public abstract void startEngine();
public void refuel() {
System.out.println("Refueling...");
}
}
3. Defining Abstract Methods and Fields
Abstract classes can declare fields and constructors, unlike interfaces. In the example below, we define common fields and an abstract method that must be implemented by subclasses.
public abstract class Employee {
protected String name;
protected double baseSalary;
public Employee(String name, double baseSalary) {
this.name = name;
this.baseSalary = baseSalary;
}
public abstract double calculateSalary();
}
4. Implementing Abstract Classes
Concrete subclasses extend the abstract class and provide implementations for all abstract methods. This ensures flexibility while preserving a common contract.
class FullTimeEmployee extends Employee {
public FullTimeEmployee(String name, double baseSalary) {
super(name, baseSalary);
}
@Override
public double calculateSalary() {
return baseSalary;
}
}
5. Custom Logic in Subclasses
Each subclass can tailor the behavior of abstract methods. Here, PartTimeEmployee
computes salary differently from FullTimeEmployee
.
class PartTimeEmployee extends Employee {
private int hoursWorked;
private double hourlyRate;
public PartTimeEmployee(String name, int hoursWorked, double hourlyRate) {
super(name, 0);
this.hoursWorked = hoursWorked;
this.hourlyRate = hourlyRate;
}
@Override
public double calculateSalary() {
return hoursWorked * hourlyRate;
}
}
6. Running the Application
The main
method demonstrates how abstract classes support polymorphism. Objects of different subclasses can be treated uniformly as instances of the abstract class.
public class AbstractClassesDemo {
public static void main(String[] args) {
Employee emp1 = new FullTimeEmployee("Alice", 3200);
Employee emp2 = new PartTimeEmployee("Bob", 80, 25);
emp1.printInfo();
System.out.println("Salary: " + emp1.calculateSalary());
emp2.printInfo();
System.out.println("Salary: " + emp2.calculateSalary());
}
}
7. Key Characteristics
- Abstract classes cannot be instantiated.
- They may contain both abstract and concrete methods.
- They can have constructors, instance variables, and access modifiers.
- Subclasses must implement all abstract methods or be declared abstract themselves.
8. Limitations
- Java supports only single inheritance, so combining behaviors from multiple sources isn’t possible.
- They are less flexible than interfaces when dealing with unrelated classes.
Conclusion
Abstract classes in Java offer a balanced mechanism for enforcing structure while supporting shared functionality. They are best suited for situations where subclasses share state and behavior but require specialized logic.
You can find the complete code of this article here in GitHub.
Pingback: Abstract Classes and Interfaces in Java
Pingback: Interfaces in Java