74.接口
在Java中,除了可以使用抽象类来实现一定程度的抽象外,还可以定义一种特殊的“抽象类”----接口(interface)。
接口是方法声明和常量值的定义的集合。在抽象类中,有些方法被实现,而有些方法只有方法的声明,没有方法的具体实现(抽象方法),而在接口中,所有的方法都没有被实现。和抽象类中的抽象方法不一样,这些没有被实现的方法不需要加上关键字abstract来将它声明为抽象方法。
接口的定义
和类定义不同,接口的定义不使用关键字“class”,而是用另外一个关键字“interface”,接口定义的基本格式如下:
<modifier> interface <name>[extends <superinterface>] {
[<attribute_declarations>]
[<abstract_method_declarations>]
}
在接口中,也可以定义属性,但它的成员属性都会被自动加上public、static和final,而对于接口中的方法,也会自动将它设置为public的。虽然我们可以显式的在属性前面加上public static final来修饰它,或者在方法定义前加上public来修饰,但在Java编程规范中,并不推荐这样做。
我们来看一个接口的定义。
public interface VideoDevice {
public int MIN_BRIGHTNESS = 10;
void turnOn();
void turnOff();
}
在这个接口中,定义了一个接口属性:MIN_BRIGHTNESS,用来表示最小亮度;定义了两个方法:用于表示开机的trurnOn()和用于表示关机的turnOff()。在前面我们说过,接口的属性将会被自动加上public static final修饰,所以,我们写一个应用程序来验证它:
源文件:TestVideoDevice.java
public class TestVideoDevice {
public static void main(String[] args) {
System.out.println(VideoDevice.MIN_BRIGHTNESS);
}
}
在这个类的main()方法中,直接使用“接口.属性名称”来访问接口的方法,我们将它编译并运行,将向控制台打印出如下的信息:
10
它就是接口中我们定义的属性“MIN_BRIGHTNESS”的值。从中也可以看出,接口的属性确实已经被加上了“public static”关键字。
那么,如何验证它还被自动加上了“final”关键字呢?很简单,只需要在TestVideoDevice的main()方法中写一条语句,试图修改MIN_BRIGHTNESS的值,看看会发生什么结果就可以了:
VideoDevice.MIN_BRGHTNESS = 100;
重新编译这个程序,将会出现如下的错误:
TestVideoDevice.java:5: cannot assign a value to final variable MIN_BRIGHTNESS
VideoDevice.MIN_BRIGHTNESS = 100;
^
1 error
很显然,属性MIN_BRIGHTNESS确实已经被加上了“final”修饰符。
接口的继承
接口和类类似,也可以从一个父接口中派生。接口的继承也是使用“extends”关键字来完成。
接口继承的基本语法如下:
<modifier> interface <name>
[ extends <super_interface> ,<super_interface>]{
[<attribute_declarations>]
[<abstract_method_declarations>]
}
和类继承类似,继承的接口也具有了父接口的特性。和类的继承不同的是,在接口的继承中,可以继承多个接口,只需要将继承的各个接口用逗号“,”隔开就可以了。
下面我们来看一个接口继承的例子。
假设我们需要定义一个视听设备,它应该同时具有可视化设备VideoDevice的特性,又有可发声设备AudioDevice的特性,我们就可以将这个视听设备同时继承VideoDevice和AudioDevice:
在前面的例子中,我们已经定义了VideoDevice接口,所以,在这里我们还需要定义一个AudioDevice接口:
public interface AudioDevice {
public int MIN_VOLUME = 5;
void turnOn();
void turnOff();
void tuneVolume(int volume);
}
然后,我们来定一个接口“AVDevice”,让它同时继承接口“VideoDevice”和“AudioDevice”:
public interface AVDevice extends VideoDevice,AudioDevice{
void shiftChannel();
}
除了从“AudioDevice”和“VideoDevice”继承的方法外,在这里新增了一个方法:shiftChannel()。
现在,我们可能会对Java中的继承方式会有了更深的了解:所谓Java不支持多继承,指的是不支持类的多继承。
使用接口
对于抽象类,我们在子类中用“extends”来继承它。但是,对于接口,在子类中必须要用另外一个关键字“implements”来“实现”它。
一个“实现”了接口的类,必须将它实现的接口中的方法都实现,或者,将没有实现的方法定义为抽象的方法,此时,类也必须定义为抽象类。
类实现接口的语法格式如下:
<modifier> class <name> [ extends <superclass> ]
[implements <interface> [,<interface>]* ] {
<declarations> *
}
在Java中,一个类只能继承一个父类,也就是说,Java不支持多继承。但是,一个类可以实现多个接口。通过接口,可以模拟实现多继承。
一个类可以继承一个父类,并且同时实现一个或多个接口。在多个接口之间用“,”来分割开。
我们来看一个实现接口的例子。
interface Metal{
public void twinkle();
}
在这里定义了一个“金属”的接口:Metal,在这个接口中,有一个方法:twinkle(),用来表示金属的闪光光泽。
源文件:Substitution.java
interface Substitution{
public void exchange();
}
这里定
义的是一个“交换物”的接口,这个接口只声明了一个方法:exchange(),用来表示等价交换。
public class Gold implements Substitution, Metal {
/**
* 实现Substitution的exchange()方法
*/
public void exchange() {
System.out.println("Exchange");
}
/**
* 实现Metal中的方法
*/
public void twinkle() {
System.out.println("Shining");
}
public static void main(String args[]) {
Gold gold = new Gold();
gold.exchange();
gold.twinkle();
}
}
然后我们定义了一个“黄金”类用来表示黄金这个实体。黄金同时具有“金属”和“等价交换物”的特点,在这边我们同时实现了“Metal”和“Substitution”这两个接口,然后,在这个类中将两个接口中的方法实现。这样,就实现了“多继承”的功能。
提示:
实现接口的时候必须在实现的方法前面加上public,这是因为在接口中默认的方法修饰符是public。