1.接口概述
接口是一种用来定义程序的协议,它用于描述类或结构的一组相关行为。接口是由抽象类衍生出来的一个概念,并由此产生了一种编程方式,可以称这种编程方式为面向接口编程。面向接口编程就是将程序的业务逻辑进行分离,以接口的形式去对接不同的业务模块。接口中不实现任何业务逻辑,业务逻辑由接口的实现类来完成。当业务需求变更时,只需要修改实现类中的业务逻辑,而不需要修改接口中的内容,以减少需求变更对系统产生的影响。
下面通过现实生活中的的例子来类比面向接口编程。例如,鼠标、U盘等外部设备通过USB插口来连接计算机,即插即用,非常灵活。如果需要更换与计算机进行连接的外部设备,只需要拔掉当前USB插口上的设备,把新的设备插入即可,这就是面向接口编程的思想。
在Java中,使用接口的目的是为了克服单继承的限制,因为一个类只能有一个父类,而一个类可以同时实现多个父接口。在JDK 8之前,接口是由全局常量和抽象方法组成的。JDK 8对接口进行了重新定义,接口中除了抽象方法外,还可以定义默认方法和静态方法,默认方法使用default关键字修饰,静态方法使用static关键字修饰,且这两种方法都允许有方法体。
2.接口定义
接口的定义与类的定义类似,包括接口声明和接口体两部分,接口声明使用interface关键字,接口定义的语法格式如下所示:
public interface 接口名 [extends 接口1,接口2...] {
[public] [static] [final] 数据类型 常量名 = 常量; //常量的定义
[public] [abstract] 返回值的数据类型 方法名(参数列表); //抽象方法
[public] static 返回值的数据类型 方法名(参数列表){} //静态方法
[public] default 返回值的数据类型 方法名(参数列表){} //默认方法
}
3.接口实现
接口本身不能直接实例化,接口中的抽象方法和默认方法只能通过接口实现类的实例对象进行调用。实现类通过implements关键字实现接口,并且实现类必须重写接口中所有的抽象方法。需要注意的是,一个类可以同时实现多个接口,实现多个接口时,多个接口名需要使用英文逗号“,”分隔。
[public] class 类名 implements 接口1,接口2{
// 类体定义
}
4.接口案例
- 案例需求
设计一个名为Swimmable的接口,其中包含void swim()方法;设计另一个名为Flyable的接口,其中包含void fly()的方法。
定义一个Duck类实现上述两个接口。
定义测试类,演示接口类型的使用。
- Swimmable接口
public interface Swimmable {
public abstract void swim();
}
-
Flyable接口
public interface Flyable {
public abstract void fly();
}
- Duck类
public class Duck implements Swimmable,Flyable{
@Override
public void fly() {
System.out.println("小鸭在飞...");
}
@Override
public void swim() {
System.out.println("小鸭在游泳...");
}
}
- 测试类
public class TestDuck {
@Test
public void test(){
Duck duck = new Duck();
duck.swim();
duck.fly();
}
}
5.练习1
- 案例需求
设计一个名为Area的接口,其中包含double getArea()方法;设计另一个名为Perimeter的接口,其中包含double getPerimeter()的方法。
定义一个Circle类实现上述两个接口,输入半径radius计算圆的面积和周长。
定义测试类,演示接口类型的使用。
- Area接口
public interface Area{
public abstract double getArea();
}
- Perimeter接口
public interface Perimeter{
public abstract double getPerimeter();
}
- Circle类
public class Circle implements Area,Perimeter{
private double radius;
public void setRadius(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
@Override
public double getPerimeter() {
return 2 * Math.PI * radius;
}
}
- 测试类
public class TestCircle {
@Test
public void test(){
Circle c = new Circle();
c.setRadius(1);
System.out.println("面积是:" + c.getArea());
System.out.println("周长是:" + c.getPerimeter());
}
}
6.练习2
- 案例需求
设计一个名为Clock的接口,其中包含void displayTime()方法;设计另一个名为Alarm的接口,其中包含void setAlarm(int hour,int minute)方法和void ring()方法。
定义一个DigitalClock类实现上述两个接口,实现显示当前时间、设置闹钟和响铃。
定义测试类,演示接口类型的使用。
- Clock接口
public interface Clock {
void displayTime();
}
- Alarm接口
public interface Alarm {
void setAlarm(int hour,int minute);
void ring();
}
- DigitalClock类
public class DigitalClock implements Clock,Alarm{
private int hour;
private int minute;
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = hour;
}
public int getMinute() {
return minute;
}
public void setMinute(int minute) {
this.minute = minute;
}
@Override
public void setAlarm(int hour, int minute) {
this.hour = hour;
this.minute = minute;
}
@Override
public void ring() {
System.out.println("叮铃铃,现在时间是:" + hour + ":" + minute);
}
@Override
public void displayTime() {
System.out.println("当前时间是:" + LocalTime.now());
}
}
- 测试类
public class TestDemo {
@Test
public void test(){
DigitalClock dc = new DigitalClock();
dc.displayTime();
dc.setHour(8);
dc.setMinute(20);
dc.ring();
}
}
7.思考
设计一个接口,定义其抽象方法;设计另一个接口,定义其抽象方法。
定义一个具体类实现上述两个接口。
定义测试类,演示接口类型的使用。