Opening Scenario
You're building a billing module. It needs to send receipts. You start with one way (email) and know a second is coming (SMS). You want the rest of the codebase not to care which one.
Your first draft:
// Java
class ReceiptSender {
void send(Receipt r) {
EmailClient.send(r.toEmail());
}
}A week later, product wants SMS too. You think about three options:
- Interface:
interface Sender { void send(Receipt r); }— letEmailSenderandSmsSenderboth implement it. - Abstract class:
abstract class Sender { ... }— have both extend it, sharing common code. - Plain concrete class with a field: composition with a
Transportfield.
All three can work. The intern asks "but why can't we just use interfaces everywhere?" and someone answers "because abstract classes let you share implementation." But then — isn't that what composition does too?
What's the actual distinction, and when is each the right choice?
Question Progression
Q1: What problem does an interface solve that a concrete class doesn't?
Question: Why…
In the full tutorial
- When to Reach for This