1

假设我们有一个接口A,由类实现B

public interface A {
    public int getValueForName(String name);
}

public class B implements A {

    public int getValueForName(String name) {
        //implementation
    }

    public String getNameForValue(int value) {
        //implementation
    }

}

如果程序员A在每次引用 of 的实例时始终使用 type B,那么任何方法,比如getNameForValue()定义在B但未指定 in 的A方法都是隐藏的,并且不能被任何持有 type 引用的代码访问A

这种方法似乎有一个致命的缺陷。一段代码如何引用B(类型A)访问的实例getNameForValue()

4

3 回答 3

3

真正的缺陷是接口的契约没有得到尊重。如果我使用接口,我不应该关心除了接口中定义的方法之外的任何其他方法。

如果接口没有定义我想要使用的方法,那么要么需要更新接口以适应新方法,要么我需要使用不同的接口。

举个例子,Collection. 如果我有一个绑定到 合同的实例Collection,那么我可以访问Iterator. 但是,我知道我要返回的元素是 type List,我想使用ListIterator更强大的而不是。

问题是它Collection没有为我定义任何访问ListIterator. 所以,我只有一个选择(因为我不能只是去Collection不必要地更新界面):改用List界面。

如果您在自己的代码中遇到这种情况,则您的接口不支持它们需要的方法。在接口级别而不是实例级别添加该支持。

于 2013-10-14T03:28:01.377 回答
1

一段引用 B 实例(类型 A)的代码如何访问 getNameForValue()?

通过将实例转换为类型 B。

接口的目的之一是定义两种或多种类型共有的方法。这并不意味着您将为每种可能类型的每种可能组合定义接口方法,而只是那些您希望通过接口公开的所有类型共有的方法。

因此,根据定义,拥有接口类型的实例假定原始类型中可能存在您无法通过接口访问的方法。这就是它的工作原理。

您可能拥有接口的另一个原因是指定功能。所以如果一个类是可迭代的,那就意味着它可以被迭代。如果我试图获取一个 Iterable 实例,我关心类中实现 Iterable 方法的方法,但我不关心任何其他方法,因为它们与 Iterable 能力没有任何关系。

简而言之,这是一个特点,而不是一个缺陷。

于 2013-10-14T03:33:40.013 回答
1

从一个更真实的例子来看它。如果我被蒙上眼睛,你告诉我面前有一只家庭宠物,我该怎么办?大概是宠物吧。现在,如果你告诉我它是一只仓鼠,我也可以把它放在轮子里让它到处跑(另一方面,我的猫不会接受这个想法)。

当您将变量声明为接口(或更高级别的类)时,例如您的A,它与上面示例中的家庭宠物相同。因此,并非所有方法都可供您使用。

要知道它是仓鼠,还是B必须取下眼罩。在 Java 的情况下,这意味着调用instanceof然后将变量转换为B. 您需要instanceof确保演员表是安全的。当然,除非您知道该事物是 a B,在这种情况下,您可能希望实际将其声明为 aB开始。

如果你发现自己在铸造,你可能对你的设计做了一些“错误”的事情。由于 Java 有了泛型,因此很少需要再进行强制转换。

于 2013-10-14T03:41:40.243 回答