Class relationships and notation
Class diagrams are the lingua franca of LLD. You don't need full UML — but you should be fluent in the basics.
The five relationships
| Relationship | Symbol | Meaning | Example |
|---|---|---|---|
| Inheritance ("is-a") | extends / arrow with triangle | Subclass IS-A parent | Car extends Vehicle |
| Composition ("contains, owns") | Solid diamond | Whole owns part; part lifecycle tied to whole | Car has Engine (Engine ceases when Car is destroyed) |
| Aggregation ("has, but doesn't own") | Hollow diamond | Whole contains part; part can exist independently | Department has Employees (Employees exist beyond Department) |
| Association ("uses, knows about") | Plain arrow | One class refers to another | Order has-a Customer reference |
| Dependency ("depends on") | Dashed arrow | Temporary use (parameter, local variable) | OrderService.process(Payment p) — uses Payment |
Composition vs Aggregation in practice
This distinction matters because it affects ownership semantics:
- Composition: when the whole is destroyed, the parts go with it. Example: A House contains Rooms. Demolish the house, the rooms cease.
- Aggregation: when the whole is destroyed, the parts persist. Example: A Team has Players. Disband the team, the players still exist.
In code, both look similar (a field holding a reference). The distinction is semantic: who's responsible for the lifecycle? In most real systems, the answer is "they outlive different things at different rates" — aggregation is the default.
Inheritance vs Composition
"Favor composition over inheritance" — Gang of Four
Inheritance is the strongest form of coupling. Subclass inherits everything — fields, behavior, contracts. Changing the parent class can silently break the subclass.
Composition is flexible. A class composed of other classes can swap them at runtime, mock them for tests, and evolve independently.
Use inheritance when:
- There's a true "is-a" relationship (Square IS-A Shape)
- Subclasses behave Liskov-substitutably for the parent
- The hierarchy is stable and well-understood
Use composition (with interfaces) for everything else.