答案 0 :(得分:4)
以下是私有接口的示例。
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();
}
}
在课程Main
中,您可以引用Animal
并在其上调用makeNoise()
。因此,您可以拥有List
Animal
个不同类型的makeNoise()
,并为每个循环使用a来调用Main
。
但是,在课程Cow
之外,这是不可能的。您可以拥有Sheep
或makeNoise()
并在其中任何一个上调用Animal
,但界面makeNoise()
和界面方法{{1}}是不可见的。
答案 1 :(得分:1)
链接文章中的示例有点人为和人为(如奇数名称所示,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
还是{{} 1}}。在当前版本中,这将打印类似
LeafNode
如果您更改了Traversing Tree$InnerNode
Traversing Tree$LeafNode
Traversing Tree$LeafNode
以返回getRootNode
,那么它只会打印
LeafNode
简单地说,并且正如名称“私人界面”已经暗示的那样:您可以使用它来隐藏两个类共享共同祖先的事实。
答案 2 :(得分:1)
我已经调查了这个问题,并且能够找到一些更多信息。 以下是一个实际的例子
在 SaveInterface类是一种类型(即没有实现的类,它的全部 方法是抽象的)。它有一个名为SaveData()的公共成员函数。该 初始解决方案中的文档类现在实现了SaveInterface类型 以保持SaveData()方法不被客户端访问的方式 文献。
请注意,在此解决方案中,SaveHandler没有可导航的关联 Document类。这已被一个可导航的协会所取代 SaveInterface类。由于SaveData()在公开声明 SaveInterface类SaveHandler无需声明为朋友 文档类。
由于SaveHandler类不是Document类的朋友,它确实如此 无法更改任何私有成员变量或调用其任何私有成员变量 成员职能。因此保留了Document类的封装。 SaveHandler类甚至不再需要了解Document类 因为它现在依赖于一个名为SaveInterface的接口。这减少了整体 设计中的依赖关系,并创造了重用的潜力。
参与者
目标(文件)
<强>客户端强>
<强>命令强>
RequestHandler(SaveHandler)
通过对RequestInterface的引用创建。实现 命令接口使Target类可以调用Execute()成员 执行请求的功能。
在激励示例中,SaveHandler类用于创建 单独的执行线程然后调用定义的成员函数 在SaveInterface中实际保存了Document中的数据 新创建的主题。
RequestInterface(SaveInterface)
已知用途
此模式广泛用于Xerox的嵌入式实时环境中。它是 用于打破执行各种类的类中的执行线程 为他们的客户提供服务。
更多信息:http://www.objectmentor.com/resources/articles/privateInterface.pdf
答案 3 :(得分:0)
私有接口是一种强制类实现某些方法的方法,而不公开暴露该接口的实现 - 例如,您将无法创建List<MyPrivateInterface>
并将类的实例添加到它
答案 4 :(得分:0)
我认为,问题是为什么你想要“强制”你自己的类实现什么?我的意思是,它是你的类,如果你想要它实现一个方法,只需实现它。 “私人INTERface”只是用词不当。界面是您希望向外部公开的类的视图。私有化没有任何意义。
如果你问的是“包私有”接口,那有点不同,虽然不多。您可能希望有时实现一个接口,该接口在您的实现内部并且不会暴露给外部。提出一个尽管有用的例子是非常困难的(尽管不是不可能)。