接口可以看成是特殊的抽象类。即只包含抽象方法和常量的抽象类。可以通过interface关键字来定义接口。看如下代码:
interface Runner {
public static int DEFAULT_SPEED = 100;
public void run();
}
注意,run()方法,此处可以省略public abstract。因其默认就是public abstract的。
实现接口
与继承不同,一个类可以实现多个接口,实现的接口直接用逗号分隔。当然,该类需要实现这些接口中定义的所有方法;
一个类可以通过implements关键字”实现”接口。一个类实现了某个接口后必须实现该接口中定义的所有方法。看下面的代码,类实现了接口并实现了方法:
class AmericanCurl implements Runner , … {
public void run() {
System.out.println(“run…”);
}
}
另外需要说明的一点,接口可以作为一种类型声明变量,一个接口类型的变量可以引用实现了该接口的类的对象;通过该变量可以调用该接口中定义的方法(具体的实现类提供了方法的实现)。代码如下所示:
Runner runner = new AmericanCurl();
此句代码为,一个接口类型变量,引用了子类的对象。调用时,调用的是子类对象的具体的实现。
接口的继承
接口间可以存在继承关系,一个接口可以通过extends关键字继承另外一个接口。子接口继承了父接口中定义的所有方法。代码如下所示:
interface Runner {
public void run();
}
interface Hunter extends Runner {
public void hunt();
}
class AmericanCurl implements Hunter {
public void run() {… … …}
public void hunt() {… … …}
}
说明:AmericanCurl实现了Hunter,必须实现Hunter接口中的hunt方法以及其父接口Runner中的run方法。
接口和抽象类的区别
一个类只能继承一个抽象类,但可以实现多个接口。
抽象类中可以包含抽象方法和非抽象方法,而接口中的所有方法均为抽象的。
子类继承抽象类必须实现抽象类中所有抽象方法,否则子类也必须是抽象类。而子类实现接口则必须实现接口中的所有抽象方法。
“接口是个规范”,这句没错。
“不如直接就在这个类中写实现方法岂不是更便捷”,你怎么保证这个接口就一个类去实现呢?如果多个类去实现同一个接口,程序怎么知道他们是有关联的呢?
既然不是一个类去实现,那就是有很多地方有用到,大家需要统一标准。甚至有的编程语言(Object-C)已经不把接口叫 interface,直接叫 protocol。
统一标准的目的,是大家都知道这个是做什么的,但是具体不用知道具体怎么做。
比如说:
我知道 Comparable 这个接口是用来比较两个对象的,那么如何去比较呢?
数字有数字的比较方法,字符串有字符串的比较方法,学生(自己定义的类)也有自己的比较方法。
然后,在另外一个负责对象排序(不一定是数字喔)的代码里面,肯定需要将两个对象比较。
这两个对象是什么类型呢?
Object a,b?肯定不行,a > b 这样的语法无法通过编译。
int a,b?也不行?一开始就说了,不一定是数字。
….
所以,Comparable 就来了。他告诉编译器,a b 两个对象都满足 Comparable 接口,也就是他们是可以进行比较的。具体怎么比较,这段程序不需要知道。
所以,他需要一些具体的实现,Comparable 接口有一个方法,叫 compareTo。那么这个方法就是用来取代 <、> 这样的运算符。
因为运算符是编译器保留给内置类型(整数、浮点数)进行比较用的,而不是一个广义的比较运算。
如果你可以明白 JDK 自身库里面诸如 Comparable 这样已经有的接口,那么就很容易理解自己在开发程序的时候为什么需要用到接口了。