实现接口如何提供额外的功能?

时间:2014-09-12 07:34:34

标签: java

我理解接口是类的契约,如果类实现了接口,那么接口中的所有方法都必须在类中。

以下是涉及此question的接口的示例,这让我感到困惑:

public class Contact implements Comparable<Contact> {

    private String name;

    public int compareTo(Contact other) {
        return name.compareTo(other.name);
    }
}

然后,您可以显然创建ArrayList并按名称对其进行排序。

List<Contact> contacts = new ArrayList<Contact>();
Collections.sort(contacts);

但如果Contract没有这样实现Comparable

public class Contact {

    private String name;

    public int compareTo(Contact other) {
        return name.compareTo(other.name);
    }
}

即使Collections.sort方法仍然存在,调用compareTo也会出现编译时错误。

显然,实现接口可以提供额外的功能。除了强制执行结构之外,接口的目的是什么?

3 个答案:

答案 0 :(得分:1)

因为如果Contact implements Comparable<Contact>,则Contact Comparable<Contact>

让我们来看看源代码,在ComparableTimSort.countRunAndMakeAscending()的深处有一行:

if (((Comparable) a[runHi++]).compareTo(a[lo]) < 0)

相关位是((Comparable) a[runHi++]) - a[runHi++] 强制Comparable,然后在上调用compareTo为a Comparable

所以如果Contact implements Comparable<Contact>我可以这样做:

final Comparable<Contact> contact = new Contact();

如果没有,那么我显然无法将实例分配给Comparable类型,因此我不知道(不使用反射)Contact有哪些方法。

通过实现Comparable我告诉编译器这个类 Comparable因此可以在必要时被视为一个。必须实施这些方法只是其副作用。

至于为什么编译时而不是运行时错误,您只需要查看方法Collections.sort的声明即可找到:

public static <T extends Comparable<? super T>> void sort(List<T> list)

所以这个方法是generic method,它的签名要求List<T> T extends Comparable<? super T>。这让我们分解一下有点棘手。

我们需要Textends Comparable<? super T>。因此T需要implements Comparable<? super T>Comparable的某些子类。 ? super T表示Comparable类型T或任何超类型可以是compareTo - 即如果您的Object可以排序T,那么它也可以对{{1}}进行排序(通过Liskov替换原则)。

答案 1 :(得分:0)

上面的答案是技术问题,但从设计的角度来看,它们在程序层之间创建了一层抽象。这在设计复杂系统时很重要,因为它减少了类之间的依赖关系,并允许更高的可维护性。

答案 2 :(得分:0)

其他答案给出了更常见的接口用法。我还在考虑另外两个:

  • 简单的标记。 Serializable不包含任何方法,也不包含常量,只是声明可以将类的实例成功序列化为流并反序列化。
  • JDK代理。 Proxy只能代理接口。因此,要代理类,必须首先将其公共方法导出到一个或多个接口。它通常用在Spring框架AOP中。