โ Back to OOP Concepts
โ๏ธ
Principles
Interface Segregation
Clients should not be forced to depend on interfaces or methods they do not use โ prefer many small, focused interfaces over one large general-purpose one.
The Problem
A "fat" interface with many unrelated methods forces every implementing class to provide (or stub out) methods it doesn't need, leading to empty or throwing implementations and tight coupling between unrelated clients.
How It Works
- โบSplit large interfaces into smaller, role-specific ones (e.g., Printable, Scannable instead of one Machine interface)
- โบClasses implement only the interfaces relevant to their behavior
- โบClients depend only on the methods they actually call
- โบReduces ripple effects โ changes to an unused method no longer force changes in unrelated classes
When to Use
โAn interface has methods that only some implementers need
โImplementing classes throw "not supported" for some interface methods
โDesigning plugin/capability systems (e.g., a printer that can print but not scan)
Real-World Examples
๐
iOS
Separate protocols like UITableViewDataSource and UITableViewDelegate instead of one giant protocol
๐ค
Android
Separate listener interfaces like OnClickListener and OnLongClickListener
๐
Web
Splitting a generic Repository interface into separate Readable and Writable interfaces
Code Examples
Swift
// โ Fat interface forces SimplePrinter to implement scan()/fax() too
// protocol Machine { func print(); func scan(); func fax() }
// โ
Segregated interfaces โ implement only what you support
protocol Printer {
func print(_ document: String)
}
protocol Scanner {
func scan() -> String
}
struct SimplePrinter: Printer {
func print(_ document: String) {
print("Printing: \(document)")
}
}
struct AllInOnePrinter: Printer, Scanner {
func print(_ document: String) { print("Printing: \(document)") }
func scan() -> String { "Scanned document" }
}