SOLID PrinciplesLiskov Substitution PrincipleMedium⏱️ ~3 min

Applying LSP: Library Management System

Consider a library management system where different types of library items have different lending rules. LSP ensures that all items can be treated uniformly by the lending system.

Initial Design (Violates LSP)

LibraryItem
- title: String
- id: String
+ checkOut(member): Result
+ checkIn(): Result
+ calculateLateFee(days): Money
Book
+ checkOut(member): Result
+ calculateLateFee(days): Money
ReferenceBook
+ checkOut(member): Result
+ calculateLateFee(days): Money

Problem: ReferenceBook cannot be checked out (reference materials stay in library). The checkOut() method must throw an exception or return an error, violating the parent's contract. Client code expecting all LibraryItem objects to be lendable breaks.

function processCheckout(item: LibraryItem, member: Member) {
result = item.checkOut(member)
if result.isSuccess() {
// This assumption fails for ReferenceBook!
sendConfirmationEmail(member)
}
}

LSP-Compliant Solution

LibraryItem
- title: String
- id: String
+ getDetails(): ItemDetails
+ isAvailable(): boolean
LendableItem
- dueDate: Date
+ checkOut(member): Result
+ checkIn(): Result
+ calculateLateFee(days): Money
ReferenceItem
- location: String
+ reserve(member): Result
+ getLocation(): String
▲ ▲
Book
DVD
Encyclopedia
Magazine

Key improvements:

  • LibraryItem contains only operations common to all items
  • LendableItem adds checkout capability for items that can leave the library
  • ReferenceItem adds reservation capability for in-library use only
  • All subtypes are substitutable within their hierarchy
Interview Tip: When designing hierarchies, start with the most general abstraction and add specialized interfaces for additional capabilities. This follows the Interface Segregation Principle (ISP) and naturally supports LSP by not forcing subclasses to implement irrelevant operations.

Client Code Benefits

function processLending(item: LendableItem, member: Member) {
// All LendableItem subtypes work correctly
result = item.checkOut(member)
if result.isSuccess() {
sendConfirmationEmail(member)
}
}

function searchCatalog(query: String): List<LibraryItem> {
// Can return mix of lendable and reference items
// Client handles based on actual type
}
💡 Key Takeaways
Separate lendable and non-lendable items into different hierarchies
Base class should only define operations that all subclasses can meaningfully implement
Use intermediate abstractions (LendableItem) to group related behaviors
Each hierarchy level maintains LSP by honoring all parent contracts
Client code can work with appropriate abstraction level without type checking
📌 Examples
1Library system with lendable books vs reference-only encyclopedias
2Separating concerns into LendableItem and ReferenceItem hierarchies
← Back to Liskov Substitution Principle Overview
Applying LSP: Library Management System | Liskov Substitution Principle - System Overflow