The examples in the related article are a bit far-fetched and artificial (as the odd names A , B , etc. have already indicated). However, let me focus on the part of the quote your question refers to:
"... without adding type information (that is, without the permission of any promotion).
A class can offer several (public or private) implementations of this interface. But the key point:
No one can ever understand that they implement this interface .
Just because the interface is not public.
I tried to create an example showing a possible application case. Of course, this is still far-fetched, but it may make the point more obvious. Suppose you want to simulate a Tree data structure consisting of Node objects. These can be InnerNode objects (which have child nodes) or LeafNode objects (which have no children).
Such a class can be implemented as follows:
class Tree { // The private interface private interface Node { List<Node> getChildren(); } // Both are public implementations public class InnerNode implements Node { @Override public List<Node> getChildren() { return Arrays.<Node>asList(getLeafNode(), getLeafNode()); } } public class LeafNode implements Node { @Override public List<Node> getChildren() { return Collections.emptyList(); } } // These return the concrete, public types public InnerNode getInnerNode() { return new InnerNode(); } public LeafNode getLeafNode() { return new LeafNode(); } // This returns the private interface type public Node getRootNode() { // Both concrete types can be returned here, // because they both implement the interface return getInnerNode(); // Works //return getLeafNode(); // Works } // This uses only the interface type public void traverseNode(Node node) { System.out.println("Traversing "+node); for (Node child : node.getChildren()) { traverseNode(child); } } }
In the external main method, you can observe the restrictions imposed by the private interface:
public static void main(String[] args) { Tree tree = new Tree();
In this example, you can call traverseNode , passing in the Node that getRootNode returns, regardless of whether this node is InnerNode or LeafNode . In the current version, it will print something like
Traversing Tree$InnerNode Traversing Tree$LeafNode Traversing Tree$LeafNode
If you changed getRootNode to return a LeafNode , then it will only print
Traversing Tree$LeafNode
Simply put, and as the name "private interface" already says: you can use this to hide the fact that the two classes share a common ancestor.