LSP

Subclasses should always be able to substitute for their parent classes.

  • That is, the principle states that when a subtype (child class) is used in place of its supertype (parent class), the program’s behavior should remain unchanged.
  • A responsibility is synonymous with a role or a reason for change. If a single class changes for multiple reasons, it indicates it has more than one responsibility.
  • “Only one role”

Contract (계약)

  • A contract is a design approach that clearly defines and adheres to the pre-conditions (input conditions), post-conditions (output conditions), invariants, etc., of a method.
  • 📌 LSP is the principle that “child classes must also uphold this contract.”
    • Even if a subclass overrides a parent’s method, it must not violate the existing contract.

Example

Bad example

class Bird {
 
    void fly() { System.out.println("날아간다"); } // Flies
}
 
class Ostrich extends Bird {
 
    void fly() { throw new UnsupportedOperationException(); }
}

An Ostrich is a Bird but cannot fly. This breaks the “ability to fly” contract of a Bird.

Good example

class Report {
 
    String title;
    String content;
}
 
class ReportPrinter {
 
    void print(Report report) { ... }
}
 
class ReportSaver {
 
    void saveToFile(Report report) { ... }
}

Each class now has only one responsibility. The reasons for changes are clearly separated.

MethodExplanation
Separate into functional classesDon’t put multiple roles into a single class
Separation of Concerns (SoC)Clearly separate UI, logic, repository, etc.
Design for a single responsibilityCreate a structure where there’s only one reason for change