这是私有接口的示例。
public class Main {
private interface Animal {
void makeNoise();
}
public static final class Cow implements Animal {
@Override
public void makeNoise() {
System.out.println("Moo!");
}
}
public static final class Sheep implements Animal {
@Override
public void makeNoise() {
System.out.println("Bah!");
}
}
public static void main(String[] args) {
List<Animal> animals = Arrays.asList(new Cow(), new Sheep());
for (Animal animal : animals)
animal.makeNoise();
}
}
Run Code Online (Sandbox Code Playgroud)
在类中,Main您可以引用Animal并调用makeNoise()它。因此,您可以拥有不同类型的Listof Animal,并使用 for every 循环来调用makeNoise()所有类型。
然而,在课堂之外Main这是不可能的。您可以使用 aCow或 aSheep并调用makeNoise()其中任何一个,但接口Animal和接口方法makeNoise()是不可见的。
链接文章中的示例有点做作和人为(正如已经由奇怪的名称、 等所表明的那样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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
在外部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());
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,您可以调用traverseNode,传入 所Node返回的getRootNode,无论该节点是 aInnerNode还是 a LeafNode。在当前版本中,这将打印类似的内容
Traversing Tree$InnerNode
Traversing Tree$LeafNode
Traversing Tree$LeafNode
Run Code Online (Sandbox Code Playgroud)
如果您更改getRootNode为 return a LeafNode,那么它只会打印
Traversing Tree$LeafNode
Run Code Online (Sandbox Code Playgroud)
简而言之,正如“私有接口”这个名称所暗示的那样:您可以使用它来隐藏两个类共享共同祖先的事实。