类中的私有接口

时间:2014-12-20 11:40:12

标签: java oop interface software-design

Here我发现了这句话:

  

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

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

5 个答案:

答案 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之外,这是不可能的。您可以拥有SheepmakeNoise()并在其中任何一个上调用Animal,但界面makeNoise()和界面方法{{1}}是不可见的。

答案 1 :(得分: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);
        }
    }
}

在外部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)

我已经调查了这个问题,并且能够找到一些更多信息。 以下是一个实际的例子

enter image description here

在 SaveInterface类是一种类型(即没有实现的类,它的全部 方法是抽象的)。它有一个名为SaveData()的公共成员函数。该 初始解决方案中的文档类现在实现了SaveInterface类型 以保持SaveData()方法不被客户端访问的方式 文献。

请注意,在此解决方案中,SaveHandler没有可导航的关联 Document类。这已被一个可导航的协会所取代 SaveInterface类。由于SaveData()在公开声明 SaveInterface类SaveHandler无需声明为朋友 文档类。

由于SaveHandler类不是Document类的朋友,它确实如此 无法更改任何私有成员变量或调用其任何私有成员变量 成员职能。因此保留了Document类的封装。 SaveHandler类甚至不再需要了解Document类 因为它现在依赖于一个名为SaveInterface的接口。这减少了整体 设计中的依赖关系,并创造了重用的潜力。

参与者

目标(文件)

  • 定义客户端的公共接口。
  • 构造RequestHandler(SaveHandler)对象,并将RequestInterface(SaveInterface)类的实例传递给RequestHandler。 - 在激励示例中,Document类导出允许的接口 客户端启动异步保存。

<强>客户端

  • 客户端使用导出的Target接口执行特定的操作 功能。

<强>命令

  • 使用Command接口因为它很可能是 目标界面将要创建许多不同种类的 RequestHandler对象。如果所有这些对象都实现了Command 接口然后可以使用Factory2来创建个人 RequestHandler对象。

RequestHandler(SaveHandler)

  • 通过对RequestInterface的引用创建。实现 命令接口使Target类可以调用Execute()成员 执行请求的功能。

  • 在激励示例中,SaveHandler类用于创建 单独的执行线程然后调用定义的成员函数 在SaveInterface中实际保存了Document中的数据 新创建的主题。

RequestInterface(SaveInterface)

  • 指定特定请求的抽象接口。

enter image description here

已知用途

此模式广泛用于Xerox的嵌入式实时环境中。它是 用于打破执行各种类的类中的执行线程 为他们的客户提供服务。

更多信息:http://www.objectmentor.com/resources/articles/privateInterface.pdf

答案 3 :(得分:0)

私有接口是一种强制类实现某些方法的方法,而不公开暴露该接口的实现 - 例如,您将无法创建List<MyPrivateInterface>并将类的实例添加到它

答案 4 :(得分:0)

我认为,问题是为什么你想要“强制”你自己的类实现什么?我的意思是,它是你的类,如果你想要它实现一个方法,只需实现它。 “私人INTERface”只是用词不当。界面是您希望向外部公开的类的视图。私有化没有任何意义。

如果你问的是“包私有”接口,那有点不同,虽然不多。您可能希望有时实现一个接口,该接口在您的实现内部并且不会暴露给外部。提出一个尽管有用的例子是非常困难的(尽管不是不可能)。