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:

  1. Interface: interface Sender { void send(Receipt r); } — let EmailSender and SmsSender both implement it.
  2. Abstract class: abstract class Sender { ... } — have both extend it, sharing common code.
  3. Plain concrete class with a field: composition with a Transport field.

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

Glossary history

Click dotted jargon to save explanations here.