The Machine interface describes an all-in-one office machine:
print(Document doc)scan(Document doc)copy(Document doc)
The interface is easy to read, but it makes one big promise: every Machine can print, scan and copy.
Problem
SimplePrinter can only print. But it implements Machine, so Java forces it to write scan() and copy() too. Both methods just throw UnsupportedOperationException, while the interface tells callers they work. Its print() is empty, and copy() has a copy and paste message that says "Scan not supported".
Step by step, the failure looks like this:
- A caller receives a variable typed as
Machine. - The type has
scan(), so the call compiles. - The object behind it is a
SimplePrinter. - The program crashes at runtime, because a
SimplePrintercan never scan.
If the type had honestly described the smaller ability, the compiler would have caught this mistake before the program ran.
Why It Violates ISP
No client should be forced to depend on methods it does not use.
Here, client means caller, the code that uses the interface. A caller that only prints should depend on a type that only offers printing. The big Machine interface also hurts implementers, because SimplePrinter must fake operations it cannot do.
This design causes several practical problems:
- unsupported operations fail late, at runtime;
- a caller can ask a basic printer to scan by accident;
- tests and fakes must handle methods they do not need;
- changing scan behavior affects every class that uses
Machine; - throwing methods also break LSP (the Liskov Substitution Principle: a subtype must work wherever its parent type is expected).
A better split uses Printer, Scanner, and Copier. A simple printer implements only Printer. An all-in-one device can implement all three.
Method count alone is not the test. If every caller and implementation really uses all three operations, Machine may be fine. The split helps here because the capabilities and callers differ.
See GoodCode for the focused interfaces and ISP-Notes.md for the full guide.