Gli esempi nell'articolo collegato sono un po 'artificiali e artificiali (come già indicato dai nomi dispari, A
, B
ecc ...). Tuttavia, concentriamoci sulla parte della citazione che la tua domanda si riferisce a:
"... senza aggiungere alcuna informazione di tipo (cioè, senza permettere alcun upcasting)."
La classe può offrire più implementazioni (pubbliche o private) di questa interfaccia. Ma il punto chiave è:
Nessuno sarà mai in grado di capire che implementano questa interfaccia.
Semplicemente, perché l'interfaccia non è pubblica.
Ho provato a creare un esempio che mostra un possibile caso di applicazione.Certo, è ancora artificioso, ma potrebbe rendere il punto più ovvio. Si consideri che si desidera modellare una struttura dati Tree
, costituita da oggetti Node
. Questi possono essere oggetti InnerNode
(che hanno nodi figlio) o oggetti LeafNode
(che non hanno figli).
Tale classe potrebbe essere implementata in questo modo:
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 un metodo esterno main
, si possono osservare le limitazioni imposte dall'interfaccia privato:
public static void main(String[] args) {
Tree tree = new Tree();
// The public concrete types can be used
Tree.LeafNode leafNode = tree.getLeafNode();
Tree.InnerNode innerNode = tree.getInnerNode();
// The private interface can not be used from outside:
//Tree.Node node = tree.getRootNode();
// This is possible: The class only uses its
// own private interface here
tree.traverseNode(tree.getRootNode());
}
In questo esempio, si può chiamare traverseNode
, passando il Node
restituito da getRootNode
, indipendentemente dal fatto che questo nodo sia un InnerNode
o un LeafNode
. Nella versione attuale, questo stampa qualcosa come
Traversing Tree$InnerNode
Traversing Tree$LeafNode
Traversing Tree$LeafNode
Se è stata modificata getRootNode
di restituire un LeafNode
, allora sarebbe solo stampare
Traversing Tree$LeafNode
Per dirla semplicemente, e come il nome "l'interfaccia privata" suggerisce già: È possibile utilizzare questo per nascondere il fatto che due classi condividono un antenato comune.
Possibilmente già risposto qui http://stackoverflow.com/questions/4573713/design-decisions-why-and-when-to-make-an-interface-private – emeraldjava
@emeraldjava : Ho visto quella domanda Ma non chiarisce questa frase o non riuscivo a capirlo. Potresti indicarmi una sezione o una frase pertinente? –