写在前面:博主在《软件构造》课程的的实验中遇到了需要设计接口的情况,在设计的时候毫无头绪,接下来博主将介绍自己对接口的理解与心得。
接口的概念
在java程序设计语言中,接口不是类,而是对希望符合这个接口的类的一组需求。
我们经常听到服务器提供商这样说:“如果你的类符合某个特点接口,我就会履行这项服务。”下面给出一个具体的示例。Array类中的sort方法承诺可以对对象数组进行排序,但要求满足下面这个条件:对象所属的类必须实现Comparable接口。
下面是Comparable接口的代码:
public interface Comparable
{
int compareTo(Object other);
}
这说明,任何实现Comparable接口的类都需要包含compareTo方法,这个方法有一个Object参数,并且返回一个整数。
接口中的方法都自动是public方法。因此,在接口中声明方法时,不必提供关键字public。
当然,这个接口还有一个没有明确说明的附加要求:在调用x.compareTo(y)的时候,这个compareTo方法必须确实能够比较两个对象,并返回比较的结果,即x和y哪一个更大。当x小于y时,返回一个负数;当x等于y时,返回0;否则返回一个正数。
上面的接口只有一个方法,而有些接口可能包含多个方法。接口还可以定义常量。不过,更重要的是要知道接口不能提供什么。接口绝不会有实例字段,在java 8之前,接口中绝对不会实现方法。
提供实例字段和方法实现的任务应该由实现接口的那个类来完成。因此,可以将接口看成是没有实例字段的抽象类。但是这两个概念还是有一定区别的。
现在,假设希望使用Array类的sort方法对Employee对象数组进行排序,Employee类就必须实现Comparable接口。
为了让类实现一个接口,通常需要完成下面两个步骤:
1.将类声明为实现给定的接口。
2.对接口中的所有方法提供定义。
要将类声明为实现某个接口,需要使用关键字implements:
class Employee implements Comparable
当然,这里的Employee类需要提供compareTo方法。假设希望根据员工的薪水进行比较。以下是compareTo方法的实现:
public int compareTo(Object otherObject)
{
Employee other = (Employee) otherObject;
return Double.compare(salary, other.salary);
}
在这里,我们使用了静态Double.compare方法。如果第一个参数小于第二个参数,他回返回一个负值;如果二者相等则返回0;否则返回一个正值。
我们可以做得更好一些。可以为泛型Comparable接口提供一个类型参数。
class Employee implements Comparable<Employee>
{
public int compareTo(Employee other)
{
return Double.compare(salary, other.salary);
}
...
}
请注意,对Object参数进行强制类型转换总是让人感觉不太顺眼,但现在已经不见了。
现在,我们已经看到,要让一个类使用排序服务必须让他实现compareTo方法。这是理所当然的,因为要向sort方法提供对象的比较方式。但是为什么不能在Employee类中直接提供一个compareTo方法,而必须实现Comparable接口呢?
主要原因在于java程序设计语言是一种强类型(strongly typed)语言。在调用方法的时候,编译器要能检查这个方法确实存在。在sort方法中可能会有下面这样的语句:
if (a[i].compareTo(a[j]) > 0)
{
//rearrange a[i] and a[j]
...
}
编译器必须确认a[i]一定有一个compareTo方法。如果a是一个Comparable对象的数组,就可以确保拥有compareTo方法,因为每个实现Comparable接口的类都必须提供这个方法的定义。
通过对接口的进一步理解,博主最终是完成了可复用的ADT,艰难地完成了课程实验。