Java tutorials > Core Java Fundamentals > Object-Oriented Programming (OOP) > What is the difference between abstract class and interface?

What is the difference between abstract class and interface?

Both abstract classes and interfaces are key concepts in Java that support abstraction and polymorphism, but they have distinct characteristics and use cases. Understanding their differences is crucial for designing robust and maintainable object-oriented applications.

Key Differences at a Glance

Feature Abstract Class Interface
Methods Can have both abstract and concrete methods All methods are implicitly abstract (since Java 8, interfaces can have default and static methods)
Variables Can have instance variables Can only have constants (static final)
Multiple Inheritance Not supported (only single inheritance) Supported (a class can implement multiple interfaces)
'extends' vs. 'implements' Uses extends keyword Uses implements keyword
Constructors Can have constructors Cannot have constructors
Access Modifiers Can have members with any access modifier (private, protected, public, default) Members are implicitly public (before Java 9). Java 9 introduced private methods within an interface.
State Can maintain state through instance variables Typically represents behavior contracts, less about state

Code Example: Abstract Class

This example demonstrates an abstract class Shape with an abstract method area() and a concrete method displayColor(). The Circle class extends Shape and provides an implementation for the area() method. Notice the constructor and the instance variable color, which allows the abstract class to maintain state.

abstract class Shape {
    protected String color;

    public Shape(String color) {
        this.color = color;
    }

    abstract double area();

    public String getColor() {
        return color;
    }

    public void displayColor() {
        System.out.println("Color: " + color);
    }
}

class Circle extends Shape {
    private double radius;

    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }

    @Override
    double area() {
        return Math.PI * radius * radius;
    }
}

Code Example: Interface

This example shows an interface Drawable with an abstract method draw(), a default method display(), and a static method printInterfaceName(). The Rectangle class implements the Drawable interface and provides an implementation for the draw() method. Interfaces primarily define a contract of behavior.

interface Drawable {
    void draw(); // Implicitly abstract

    default void display() {
        System.out.println("Displaying...");
    }

    static void printInterfaceName() {
        System.out.println("Drawable Interface");
    }
}

class Rectangle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle");
    }
}

Concepts Behind the Snippets

The core concept is abstraction, which allows you to define a general template for classes without specifying all the implementation details. Abstract classes can provide a partial implementation, while interfaces define a contract that implementing classes must adhere to. Polymorphism is also key as it allows treating objects of different classes in a uniform manner through their common abstract class or interface.

Real-Life Use Case

Consider a GUI framework. An abstract class Widget might define common properties and methods for all GUI elements (e.g., position, size, event handling). Different GUI elements like Button, TextField, etc., would then extend Widget and provide specific implementations. An interface like Clickable could define a onClick() method that any widget can implement to handle click events. This allows for flexible and extensible design where you can add new widgets or event handling mechanisms without modifying the core framework.

When to use them

Abstract Class: Use an abstract class when you want to provide a common base implementation for a group of related classes and share code among them. It is appropriate when there is a strong 'is-a' relationship. Abstract classes allow you to define instance variables and methods with different access modifiers.

Interface: Use an interface when you want to define a contract that multiple unrelated classes can implement. It is appropriate when you want to achieve multiple inheritance of behavior. Interfaces are suitable for defining a set of methods that a class must implement, without providing any implementation details. With default methods, interfaces can also provide some default behavior without forcing implementing classes to reimplement everything.

Memory Footprint

In terms of memory footprint, there isn't a significant difference between abstract classes and interfaces at runtime. The memory usage depends more on the instance variables of the concrete classes that inherit from the abstract class or implement the interface. However, keep in mind that abstract classes might have a slight overhead if they contain many instance variables that are not used by all subclasses.

Alternatives

Alternatives to abstract classes and interfaces include: Composition: Instead of inheritance, a class can contain instances of other classes to reuse their behavior. This can avoid the tight coupling introduced by inheritance. Functional Interfaces and Lambdas: Java 8 introduced functional interfaces and lambda expressions, which provide a concise way to define single-method interfaces and pass them as arguments to methods. Mixins (with traits in other languages): Java lacks explicit mixin support, but you can simulate some aspects using interfaces with default methods. Other languages like Scala have built-in support for traits which allow combining multiple behaviors into a class.

Pros and Cons - Abstract Class

Pros:

  • Code reusability: Common functionality can be implemented in the abstract class and inherited by subclasses.
  • State maintenance: Can maintain state through instance variables.
  • Controlled inheritance: Enforces a specific hierarchy and structure.
Cons:
  • Single inheritance: Java only allows a class to inherit from one abstract class.
  • Tight coupling: Can lead to tight coupling between the abstract class and its subclasses.

Pros and Cons - Interface

Pros:

  • Multiple inheritance: A class can implement multiple interfaces, allowing for greater flexibility.
  • Loose coupling: Promotes loose coupling between classes and interfaces.
  • Behavior contract: Clearly defines a contract that implementing classes must adhere to.
Cons:
  • No state: Cannot maintain state through instance variables (only constants allowed).
  • Potential for code duplication: Implementing classes must provide their own implementation for each method (unless default methods are used).

Interview Tip

When discussing abstract classes and interfaces in an interview, it's important to highlight the scenarios where each is more appropriate. Demonstrate your understanding of the design principles behind them. Be prepared to discuss the evolution of interfaces with the introduction of default and static methods and how that impacts the choice between using an abstract class or an interface.

FAQ

  • Can an abstract class implement an interface?

    Yes, an abstract class can implement one or more interfaces. It can choose to implement some or all of the methods defined in the interface.
  • Can an interface extend another interface?

    Yes, an interface can extend one or more other interfaces. This allows you to create a hierarchy of interfaces.
  • What is the purpose of default methods in interfaces?

    Default methods provide a default implementation for a method in an interface. This allows you to add new methods to an interface without breaking existing implementations.
  • When were default methods introduced in interfaces?

    Default methods were introduced in Java 8.
  • Can an abstract class be instantiated?

    No, abstract classes cannot be instantiated. They are designed to be subclasses by other classes that provide concrete implementations of the abstract methods.