A single interface forces every implementor to support methods they do not need. How do you fix that without breaking callers?
The fix is to split the fat interface into focused ones and let implementors pick the pieces they need. The caller that only needs printing depends on Printer, and the caller that needs both depends on a combined interface built from the two focused ones.
public class Main {
public static void main(String[] args) {
SimplePrinter p = new SimplePrinter();
p.print("hi");
MultiPrinter m = new MultiPrinter();
m.print("hi");
m.scan();
}
}
interface Printer {
void print(String text);
}
interface Scanner {
void scan();
}
interface PrintScan extends Printer, Scanner { }
class SimplePrinter implements Printer {
public void print(String text) { System.out.println("print: " + text); }
}
class MultiPrinter implements PrintScan {
public void print(String text) { System.out.println("print: " + text); }
public void scan() { System.out.println("scanning"); }
}The output shows the practical benefit. The simple printer implements one method and never has to pretend it can scan. The multi printer implements the combined contract and does both. The interfaces are arranged so that existing callers that only printed still compile, because the print method kept its name and signature in the narrowed interface.
The general rule behind this is the interface segregation principle: prefer many small, specific interfaces over a few large ones, so that clients depend only on what they use. A client that implements an interface it does not fully support is forced into empty methods or exceptions, which is a signal that the contract is too wide.
The cost is real and should be acknowledged. Splitting an interface that is already published is a breaking change, because the combined type no longer exists and existing implementations stop satisfying the old contract. In a live codebase you would keep the old interface extending the new focused ones, so the combined contract still exists and existing implementations still compile.