面向对象高级(5)接口
面向对象高级(5) 接口
接口就是规范,定义的是一组规则,体现了现实世界中“如果是...则必须能...”的思想。继承是一个"是不是"的is-a关系,而接口实现则是 "能不能"的has-a关系。
1、接口的定义格式
接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型。
引用数据类型:数组,类,枚举,接口,注解。
修饰符 interface 接口名{
//接口的成员列表:
//默认方法:
default 返回值类型 方法名(){
}
// 公共的静态常量
public static final 数据类型 变量名;//提示:前置修饰中public static final可以省略)
// 公共的抽象方法,public abstract可省略;
public abstract 返回值 方法名(){
}
// 公共的默认方法(JDK1.8以上)
// 公共的静态方法(JDK1.8以上)
// 私有方法(JDK1.9以上)
}
不能声明构造器、代码块。
2、接口的实现
(1)类实现接口(implements)
接口不能创建对象,但是可以被类实现(implements ,类似于被继承)。
类与接口的关系为实现关系,即类实现接口。实现了接口的类称为实现类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements关键字。
修饰符 class 实现类的类名 implements 接口{
// 必须:重写接口中的抽象方法,(如果实现类是抽象类,那么可以不重写)
// 可以:重写接口中的默认方法
}
修饰符 class 实现类 extends 父类 implements 接口{
//必须重写所有的抽象方法
}
注意:
- 如果接口的实现类是非抽象类,那么必须重写接口中所有抽象方法。
- 默认方法可以选择保留,也可以重写。default不能省略。
- 重写时,default单词就不要再写了,它只用于在接口中表示默认方法,到实现类中就没有默认方法的概念了
- 接口中的静态方法不能被继承也不能被重写,static不能省略
public interface Ipower {
void power();//抽象方法
default void brand(){
System.out.println("famous.");
}//默认方法
}
public class IpowerTest implements Ipower{//实现接口
public void power(){
System.out.println("Charge.");
}//重写抽象方法
public static void main(String[] args){
IpowerTest t = new IpowerTest();//创建实例对象
t.power();//调用重写后的抽象方法
}
}
(2)接口的多实现
对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。
实现格式:
1.修饰符 class 实现类 implements 接口1,接口2,接口3。。。{
// 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
// 重写接口中默认方法【可选】
}
2.修饰符 class 实现类 extends 父类 implements 接口1,接口2,接口3。。。{
// 重写接口中所有抽象方法【必须】,包括父类中的抽象方法与接口中的抽象方法,除非子类也声明为声明为抽象类才可以不重写。
// 重写接口中默认方法【可选】
}
接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次。
定义多个接口:
public interface A {
void showA();
}
public interface B {
void showB();
}
定义实现类:
public class C implements A,B {
@Override
public void showA() {
System.out.println("showA");
}
@Override
public void showB() {
System.out.println("showB");
}
}
定义测试类:
public class TestC {
public static void main(String[] args) {
C c = new C();
c.showA();
c.showB();
}
}
(3)接口的多继承
一个接口能继承另一个或者多个接口,接口的继承也使用 extends 关键字,子接口继承父接口的方法。
子接口的实现类需要将接口中所有的抽象方法都进行重写,重名的抽象方法只需要重写一次。
定义父类接口:
public interface Chargeable {
void charge();
}
定义子类接口:
public interface UsbC extends Chargeable,USB3 {
void reverse();
}
定义子接口的实现类:
public class TypeCConverter implements UsbC {
@Override
public void reverse() {
System.out.println("正反面都支持");
}
@Override
public void charge() {
System.out.println("可充电");
}
}
(4)接口与实现类对象构成多态引用
实现类 实现接口,类似于子类继承父类,因此,接口类型的变量与实现类的对象之间,也可以构成多态引用。通过接口类型的变量调用方法,最终执行的是new的实现类对象实现的方法体。
接口名 变量名 = new 实现类对象
public class USBTest {
public static void main(String[] args) {
Computer c = new Computer();
Printer p = new Printer();
c.transferData(p);//USB usb = new Printer();实际执行打印机重写后的方法。
}
}
interface USB{
void start();
void end();
}
class Computer {
public void transferData(USB usb){
System.out.println("Successfully connect.");
usb.start();
System.out.println("Transferring date...");
usb.end();
}
}//通过引用实例变量usb实现USB接口的调用
class Printer implements USB{
@Override
public void start() {
System.out.println("beginning work");
}
@Override
public void end() {
System.out.println("end work");
}
}
此处展示有关匿名对象与匿名实现类的书写:
public class USBTest {
public static void main(String[] args) {
Computer c = new Computer();
Printer p = new Printer();
c.transferData(p);//USB usb = new Print();实际执行打印机重写后的方法。
System.out.println();
c.transferData(new Printer());//创建实现类的匿名对象
System.out.println();
USB usb = new USB() {
@Override
public void start() {
System.out.println("beginning work");
}
@Override
public void end() {
System.out.println("end work");
}
};
c.transferData(usb);//创建匿名实现类的对象
System.out.println();
c.transferData(new USB() {
@Override
public void start() {
System.out.println("beginning work");
}
@Override
public void end() {
System.out.println("end work");
}
});//创建匿名实现类的匿名对象
}
}
(5)使用接口的静态成员
接口不能直接创建对象,但是可以通过接口名,直接调用接口的静态方法和静态常量。
public class TestUSB3 {
public static void main(String[] args) {
//通过“接口名.”调用接口的静态方法 (JDK8.0才能开始使用)
USB3.show();
//通过“接口名.”直接使用接口的静态常量
System.out.println(USB3.MAX_SPEED);
}
}
6、使用接口的非静态方法
接口的非静态方法也只能使用“接口名."进行调用,不能通过实现类的对象进行调用
- 对于接口的抽象方法、默认方法,只能通过实现类对象才可以调用
- 接口不能直接创建对象,只能创建实现类的对象
public class TestMobileHDD {
public static void main(String[] args) {
//创建实现类对象
MobileHDD b = new MobileHDD();
//通过实现类对象调用重写的抽象方法,以及接口的默认方法,如果实现类重写了就执行重写的默认方法,如果没有重写,就执行接口中的默认方法
b.start();
b.in();
b.stop();
//通过接口名调用接口的静态方法
// MobileHDD.show();
// b.show();
Usb3.show();
}
}
补充:
(1)类优先原则
当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的抽象方法重名,子类就近选择执行父类的成员方法。
(2)接口冲突
实现类实现了多个接口,而多个接口中存在同名同参的方法时,编译不通过,会报错。此时,必须在实现类中重写同名同参的方法。
(3)解决接口冲突后,若仍然想要调用具体的某个接口中同名同参的方法,则采用 接口名.super.方法名();的写法。
小结;
- 接口本身不能创建对象,只能创建接口的实现类对象,接口类型的变量可以与实现类对象构成多态引用。
- 声明接口用interface,接口的成员声明有限制:
- (1)公共的静态常量
- (2)公共的抽象方法
- (3)公共的默认方法(JDK8.0 及以上)
- (4)公共的静态方法(JDK8.0 及以上)
- (5)私有方法(JDK9.0 及以上)
- 类可以实现接口,关键字是implements,而且支持多实现。如果实现类不是抽象类,就必须实现接口中所有的抽象方法。如果实现类既要继承父类又要实现父接口,那么继承(extends)在前,实现(implements)在后。
- 接口可以继承接口,关键字是extends,而且支持多继承。
- 接口的默认方法可以选择重写或不重写。如果有冲突问题,另行处理。子类重写父接口的默认方法,要去掉default,子接口重写父接口的默认方法,不要去掉default。
- 接口的静态方法不能被继承,也不能被重写。接口的静态方法只能通过“接口名.静态方法名”进行调用。