Handbooks / OOP & Design Patterns / Chapter 3
Interfaces vs Abstract Classes
7 pages · ~5 min✓ Reviewed
Builds on UML Class Diagrams. Next up: SOLID Principles.
Contracts vs Partial Implementations
1. Two kinds of abstract type
- Interface = pure contract: method signatures, no state:
interface Shape { double area(); } - Abstract class = partial implementation: shared fields and concrete methods, plus abstract methods to fill in
| Interface | Abstract class | |
|---|---|---|
| State | none | fields allowed |
| Methods | signatures only | concrete + abstract |
| Models | can do | is a |
2. In Python and on instantiation
- No
interfacekeyword: useabc.ABCwith@abstractmethod - Or
typing.Protocolfor a structural (duck-typed) contract - Neither can be instantiated; unfilled abstract methods in Python raise TypeError
- Java rejects it at compile time instead
python
from abc import ABC, abstractmethod class Shape(ABC): @abstractmethod def area(self): ... try: Shape() except TypeError: print("TypeError")
output
TypeError
3. Mental model
Multiple Interface Implementation
1. Many Parents
| Java | Python | |
|---|---|---|
| Parents | one extends, many implements | many bases, ABCs or Protocols |
| Syntax | class Duck implements Flyer, Swimmer | class Duck(Flyer, Swimmer) |
| Lookup order | explicit override | MRO (C3 linearization) |
2. Diamond Problem
Default Methods and Choosing Between Them
1. Default Methods
- Java 8 default methods give an interface a body
- Add methods without breaking existing implementers
- No instance fields; only calls other interface methods
- Python: ABCs hold concrete methods
- Protocol default bodies are inherited by explicit subclasses
java
interface Logger {
void write(String m);
default void log() { write("hi"); }
}2. Interface or Abstract Class
| Interface | Abstract class |
|---|
Programming to an Interface
1. Depend on the abstraction
- Declare the interface type, construct the concrete one:
List<String> xs = new ArrayList<>(); - Python:
def run(store: Storage)takes any Storage, not one class - Accept the interface in parameters, fields and return types
- Implementations swap with no change to callers
2. Injection and testing
- Callerknows Repo only
- Repointerface
- DbRepoproduction
- InMemoryRepounit tests
Abstract Classes and the Template Method
1. The Skeleton
- Template method: the base class owns the algorithm skeleton in a concrete method
- Subclasses override only the varying steps
- Java:
finalstops subclasses overriding the skeleton
- load()fixed
- format()abstract
- save()fixed
java
abstract class Report {
final void generate() {
load(); format(); save();
}
abstract void format();
}Java
python
class Report(ABC): def generate(self): self.load(); self.format(); self.save() @abstractmethod def format(self): ...
Python
2. Hook Methods
Interfaces vs Abstract Classes Cheat Sheet
1. Side by side
| Interface | Abstract class | |
|---|---|---|
| Models | capability (can do) | shared base (is a) |
| State | none | fields, constructor |
| Per class | many | one |
| Code | default methods | concrete methods |
2. Syntax
Check yourself
In Python, class Sq(Shape): pass extends an ABC with an abstract area. When does the error appear?
- At
Sq(), as aTypeError, not at the class definition - Java would reject it at compile time
What does new Sub() print?
0: theBaseconstructor runs beforeSubfield initialisers- Never call overridable methods from a constructor
abstract class Base { Base(){ init(); } abstract void init(); } class Sub extends Base { int n = 5; void init(){ System.out.println(n); } }