类中的私有接口

tha*_*_DG 5 java oop interface software-design

在这里,我遇到了这句话:

实现私有接口是强制在该接口中定义方法而不添加任何类型信息(即不允许任何向上转换)的方法.

我发现很难理解这一点.有人可以帮我解释一下吗?

Pau*_*ton 5

这是私有接口的示例。

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()是不可见的。


Mar*_*o13 1

链接文章中的示例有点做作和人为(正如已经由奇怪的名称、 等所表明的那样AB。但是,让我们关注您的问题所引用的引用部分:

“...不添加任何类型信息(即不允许任何向上转型)。”

该类可以提供此接口的多个(公共或私有)实现。但关键点是:

没有人能够知道他们实现了这个接口

很简单,因为接口不是公开的。

我尝试创建一个示例来展示可能的应用案例。当然,这仍然是做作的,但可能会让这一点更加明显。假设您想要对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)

简而言之,正如“私有接口”这个名称所暗示的那样:您可以使用它来隐藏两个类共享共同祖先的事实。