接口与插件:
初见接口,你可能会奇怪为什么叫接口不叫插件,因为java接口的功能太像一个插件了,插上每个插件,就具有某种功能。
那么我举个例子你就明白了,比如说一个U盘就相当于一个插件,而要读取U盘的内容就得需要一个USB接口了,倘若缺少二者中的任何一个,都无法实现你想要达到的功能。
往抽象了说,电脑的外设都可以称为插件,而USB接口在电脑上可以有很多个,把电脑的PC主机抽象为一个类,那么你可以选择实现3个USB接口那么你就可以供3个插件使用并起作用(打印机,光驱),当然你也可以选择不实现,这都取决于你,至于这个插件本身的不同,USB接口并不关心,只取决于实现接口的类。这个就是现实意义中的“多态”。
接口的优缺点:
- 达到了了C++的多继承的目的。一个类可以实现多个接口,在Java中类与类是单一继承,一个类只能由一个父类,打破了继承的局限性。
- 降低了程序的耦合性,使程序能更好的被维护。
- 缺点:由于每个继承接口的类都必须实现接口内部的功能,造成代码量的迅速膨胀。
接口的default方法:
正如我们所熟知的, 接口里正常的方法是不能有函数体只能有一个类似于c++里的方法的声明而没有实现:
即使是空的方法体eclipse也会报错。
每个“继承”接口的类如果没有声明为abstract 就必须将接口里的方法全部实现,一个都不能少。
那么问题来了,倘若你想在这个类中添加一个新的方法,比如这个:
在这个接口里新加了一个test() 方法,但是为了能让程序编译能够通过我们不得不在每个继承Device接口的类中实现这个方法。这就给代码后期的维护与更新带来了很大的不便,缘于此,Java在jdk1.8版本为接口添加了一个default声明。
这个怎么使用呢?
我们看到了test方法的声明与在普通类中没有什么不同,当然除了那个public前的default。通过这个default声明我们可以在接口里实现一个类似于普通的class中的Static功能。
并且实现与否是由你自己决定的,你可以选择在继承接口的类中覆写这个方法,也可以选择不去管它。反正我们都是可以通过多态,将子类对象的引用赋给一个接口对象的引用。
我们在驱动类中创建一个接口类型的容器:
然后我们在这个容器中添加“东西”:
(注:Tv、Stopwacth、LightBulb是三个继承接口的类,其中Tv覆写了test方法)
然后我们遍历这个容器:
看下结果:
是不是感觉有种覆写基类方法的感觉......
总结:
a.有了default 我们可以在接口中实现普通类中的方法,有访问权限、函数体、返回类型。
b.我们可以通过default 可以很容易的在接口中添加新的方法,而不是必须在每个继承该接口的类中覆写该方法。减少了java的代码量。
代码附录:
public interface Device {
void turnOn();
void turnOff();
default public void test() {
System.out.println("I am a default method from interface from Device");
}
}
public class Stopwacth implements Device{
private int state;
private long startTime;
private String name;
/**
* @param state
* @param startTime
* @param name
*/
public Stopwacth(int state, long startTime, String name) {
super();
this.state = state;
this.startTime = startTime;
this.name = name;
}
@Override
public void turnOn() {
System.out.println(" The stopwatch has been turned on.");
}
@Override
public void turnOff() {
System.out.println(" The stopwatch has been turned on.");
}
public String toString() {
return "stopwatch: "+" state: "+this.state+" startTime: "+this.startTime+
" name: "+this.name;
}
}
public class Tv implements Device {
private String name;
public Tv(String initialname)
{
this.name = initialname;
}
@Override
public void turnOn() {
System.out.println(" The Tv has been turned on.");
}
@Override
public void turnOff() {
System.out.println(" The Tv has been turned off.");
}
public String toString() {
return "name: "+this.name;
}
public void test() {
System.out.println("����TV class��");
}
}
public class LightBulb implements Device{
private String name;
/**
* @param name
*/
public LightBulb(String name) {
super();
this.name = name;
}
@Override
public void turnOn() {
System.out.println(" The LightBulb has been turned on.");
}
@Override
public void turnOff() {
System.out.println(" The LightBulb has been turned on.");
}
public String toString() {
return "LightBulb:\n"+"name: "+this.name;
}
}
import java.util.ArrayList;
public class Main {
private ArrayList<Device> device = new ArrayList<Device>();
public static void main(String[] args) {
Main m = new Main();
m.addDevice();
m.display();
}
private void display() {
for(Device de:device) {
de.turnOn();
de.turnOff();
de.test();
}
}
private void addDevice() {
device.add(new Tv("ximenzi"));
device.add(new Tv("songxia"));
device.add(new Tv("changhong"));
device.add(new Stopwacth(1,13333,"kaxiou"));
device.add(new Stopwacth(2,2444,"kaxiou"));
device.add(new Stopwacth(3,4555,"kaxiou"));
device.add(new LightBulb("xiaoming"));
device.add(new LightBulb("xiaofang"));
device.add(new LightBulb("xiaohong"));
}
}