Intuition The one-line idea
No client should be forced to depend on methods it does not use. Fat interfaces should be split into smaller, role-specific ones so each implementer only "signs up" for what it actually needs.
Definition Interface Segregation Principle
The I in SOLID. It states: many client-specific (small) interfaces are better than one general-purpose (fat) interface . A class should never be forced to implement methods it doesn't care about.
The word client here means the code that depends on the interface — both the caller AND the implementer. When an interface bundles unrelated capabilities, every implementer is dragged into all of them.
Intuition Why fat interfaces hurt
When Worker declares work() AND eat(), a RobotWorker has no notion of eating. It is forced to implement eat() — usually with a stub or, worse, throw new UnsupportedOperationException(). That's a lie: the type claims an ability it doesn't have.
Three concrete pains of fat interfaces:
Forced dummy implementations → dead code, lies in the type system.
Coupling by accident — change eat()'s signature and every worker recompiles, even robots.
Misleading contracts — callers can't trust that a method actually works.
Intuition WHY ISP ≈ "SRP for interfaces"
Single Responsibility says a class should have one reason to change. ISP says an interface should have one reason to change. A fat interface serves many clients → many reasons to change → instability.
Worked example Violating ISP
interface Worker {
void work ();
void eat (); // not all workers eat!
}
class RobotWorker implements Worker {
public void work () { /* assemble cars */ }
public void eat () { throw new UnsupportedOperationException (); } // ❌ lie
}
Why is this bad? RobotWorker is forced to depend on eat(). Any code calling worker.eat() on a robot crashes at runtime — the compiler couldn't warn us.
Worked example Fixed with ISP
interface Workable { void work (); }
interface Feedable { void eat (); }
class HumanWorker implements Workable , Feedable {
public void work () { ... }
public void eat () { ... }
}
class RobotWorker implements Workable { // ✅ only what it needs
public void work () { ... }
}
Why this step? A canteen scheduler now depends only on Feedable. It cannot even reference a RobotWorker, so the bug class disappears at compile time.
Worked example Fat interface
interface Machine {
void print (Doc d );
void scan (Doc d );
void fax (Doc d );
}
Why this fails: An OldPrinter that can only print must still implement scan and fax. Worse, any new method added to Machine (say staple()) breaks every machine.
Worked example Segregated
interface Printer { void print (Doc d ); }
interface Scanner { void scan (Doc d ); }
interface Fax { void fax (Doc d ); }
class OldPrinter implements Printer { ... }
class AllInOne implements Printer , Scanner , Fax { ... }
Why this step? Composition of roles. OldPrinter's contract is now honest , and adding staple() as interface Stapler touches nobody who doesn't staple.
Worked example Counting forced dependencies
Suppose a fat interface has m m m methods and n n n implementers, where implementer i i i genuinely uses u i u_i u i of the methods. The number of forced (unused) method dependencies is
F fat = ∑ i = 1 n ( m − u i ) . F_{\text{fat}} = \sum_{i=1}^{n}(m - u_i). F fat = ∑ i = 1 n ( m − u i ) .
Why this formula? Each implementer must satisfy all m m m methods but only needs u i u_i u i ; the gap m − u i m-u_i m − u i is forced dead weight. After perfect segregation each implementer pulls in exactly u i u_i u i , so F seg = 0 F_{\text{seg}} = 0 F seg = 0 .
Numbers: m = 3 m=3 m = 3 (print/scan/fax), implementers use { 1 , 1 , 3 } \{1,1,3\} { 1 , 1 , 3 } methods.
F fat = ( 3 − 1 ) + ( 3 − 1 ) + ( 3 − 3 ) = 2 + 2 + 0 = 4 F_{\text{fat}} = (3-1)+(3-1)+(3-3) = 2+2+0 = 4 F fat = ( 3 − 1 ) + ( 3 − 1 ) + ( 3 − 3 ) = 2 + 2 + 0 = 4 forced dependencies removed by ISP.
Common mistake "More interfaces = more ISP, so split EVERY method."
Why it feels right: ISP rewards smaller interfaces, so atomizing to one-method-per-interface seems maximally compliant.
The fix: Split by cohesive role / client need , not by individual method. read() and write() that are always used together by the same client belong in one Stream interface. Over-splitting creates interface explosion and obscures intent. Cohesion, not minimal size, is the goal.
Common mistake "Throwing UnsupportedOperationException satisfies the interface."
Why it feels right: It compiles and the class technically "implements" everything.
The fix: It violates the Liskov contract — callers expect a working method. A compile-time stub is a runtime bomb. Remove the method from the interface instead.
Common mistake "ISP is the same as SRP."
Why it feels right: Both say 'keep things small / one responsibility'.
The fix: SRP is about a class's reasons to change ; ISP is about what callers are forced to depend on . A class can have one responsibility yet still expose a bloated interface to different clients.
Recall Feynman: explain to a 12-year-old
Imagine a restaurant menu that forces you to order soup, salad AND dessert together, even if you only want soup. Annoying, right? A good menu lets you pick just what you want. An interface is a menu of things a piece of code can do. ISP says: don't force code to "order" abilities it will never use — give it a small menu with only its dishes.
"Don't make me carry buttons I'll never press."
Think of a TV remote with 80 buttons when you only use 4 — that's a fat interface. ISP = a tiny remote per task.
State ISP in one sentence — then check against the definition above.
Why is throw new UnsupportedOperationException() a code smell pointing to an ISP violation?
How does ISP differ from SRP?
What does the I in SOLID stand for? Interface Segregation Principle.
State the Interface Segregation Principle. No client should be forced to depend on methods (interface members) it does not use.
What is the core symptom of an ISP violation in code? Implementers writing empty/dummy methods or throwing UnsupportedOperationException for methods they don't use.
What is a "role interface"? A small interface defined by what a specific client needs, grouping only cohesive methods used together.
ISP fix: split a fat interface by what criterion? By cohesive client role/need — NOT by individual method (avoid over-splitting).
How does ISP differ from SRP? SRP limits a class's reasons to change; ISP limits what a client is forced to depend on. ISP is "SRP for interfaces."
For m methods and implementer i using u_i, how many forced dependencies does the fat interface impose? Sum over i of (m - u_i); segregation reduces this to 0.
Which other SOLID principle is violated by stubbing an interface method with an exception? Liskov Substitution Principle (the subtype breaks the supertype's contract).
Interface Segregation Principle
Client depends only on what it uses
Forced dummy implementations
Recipe: group methods by role
Class implements multiple small interfaces
Intuition Hinglish mein samjho
Dekho, ISP ka matlab simple hai: kisi bhi class ko aise methods implement karne ke liye force mat karo jo wo use hi nahi karti. Agar tum ek bada "fat" interface banate ho — jaise Machine jisme print(), scan(), fax() sab ek saath hai — to jo printer sirf print karta hai usko bhi scan() aur fax() ka khaali (dummy) implementation likhna padega, ya UnsupportedOperationException throw karna padega. Yeh ek tarah ka jhooth hai, kyunki type bol raha hai "main scan kar sakta hoon" jabki actually nahi kar sakta.
Solution? Bade interface ko chhote role interfaces mein tod do — Printer, Scanner, Fax alag. Ab jo class jo role chahiye usko implement kare. Java mein ek class multiple interfaces implement kar sakti hai, to AllInOne teeno le lega, aur OldPrinter sirf Printer. Compile time pe hi galti pakdi jaati hai — koi galti se robot ko eat() call nahi kar sakta agar robot Feedable implement hi nahi karta.
Ek important baat: ISP ka matlab yeh nahi ki har method ka alag interface bana do. Cohesion dekho — jo methods hamesha saath use hote hain (jaise read aur write ek stream mein), unhe saath rakho. Warna interface ka explosion ho jaata hai aur code samajhna mushkil. Yaad rakho: ISP basically SRP ka interface version hai — har interface ki ek hi wajah honi chahiye change hone ki. Yeh matter karta hai kyunki kam coupling matlab kam bugs, aur change karna easy.