Примеры в связанной статье немного изобретательны и искусственны (как уже указывалось нечетными именами, A
, B
и т. Д.). Однако, давайте обратим внимание на часть цитаты, что ваш вопрос относится к:
«... без добавления каких-либо информации о типе (то есть, не допуская каких-либо приведение к базовому типу).»
Класс может предлагать несколько (публичных или частных) реализаций этого интерфейса. Но ключевым моментом является следующее:
Никто не сможет понять, что они реализуют этот интерфейс.
Просто потому, что интерфейс не является общедоступным.
Я попытался создать пример, показывающий возможный случай приложения.Конечно, это все же надуманно, но может сделать пункт более очевидным. Предположим, вы хотите смоделировать структуру данных Tree
, которая состоит из Node
объектов. Это могут быть объекты InnerNode
(у которых есть дочерние узлы) или LeafNode
объектов (у которых нет детей).
Такой класс может быть реализована следующим образом:
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);
}
}
}
Во внешнем main
метод, вы можете наблюдать за ограничений, налагаемых частного интерфейса:
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());
}
В этом примере, вы можете звоните traverseNode
, передавая в Node
, который возвращается getRootNode
, независимо от того, является ли этот узел InnerNode
или LeafNode
. В текущей версии, это будет печатать что-то вроде
Traversing Tree$InnerNode
Traversing Tree$LeafNode
Traversing Tree$LeafNode
Если вы изменили getRootNode
вернуть LeafNode
, то он будет печатать только
Traversing Tree$LeafNode
Проще говоря, и в качестве имени «частный интерфейс» уже предлагает: вы можете использовать это, чтобы скрыть факт, что два класса имеют общий предок.
Возможно, здесь уже ответил http://stackoverflow.com/questions/4573713/design-decisions-why-and-when-to-make-an-interface-private – emeraldjava
@emeraldjava : Я видел этот вопрос. Но это не разъясняет эту фразу, или я не мог ее понять. Не могли бы вы указать мне соответствующий раздел или фразу? –