JAVA基础(10)面向对象编程5——接口

 

目录

 一、接口(interface)

1.概念

2.格式

3.说明

4.接口的使用

(1)类实现接口(implements)

①定义

②格式

③注意

④举例

(2)接口的多实现(implements)

①定义

②格式

③注意

④举例

(3)接口的多继承(extends)

①定义

②注意

③举例

(4)接口与实现类对象构成多态引用

①定义

②举例

(5)使用接口的静态成员

①定义

②举例

(6)使用接口的非静态方法

 5.JDK8中相关冲突问题

(1)默认方法冲突问题

①类优先原则

②接口冲突(左右为难)

(2)常量冲突问题

总结


一、接口(interface)

1.概念

  • 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要...则必须能...”的思想。继承是一个"是不是"的is-a关系,而接口实现则是 "能不能"的has-a关系。
  • 接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型(数组,类,枚举,接口,注解 )。

2.格式

[修饰符] interface 接口名{
    //接口的成员列表:
    // 公共的静态常量
    // 公共的抽象方法
    
    // 公共的默认方法(JDK1.8以上)
    // 公共的静态方法(JDK1.8以上)
    // 私有方法(JDK1.9以上)
}

package com.atguigu.interfacetype;

public interface USB3{
    //静态常量
    long MAX_SPEED = 500*1024*1024;//500MB/s

    //抽象方法
    void in();
    void out();

    //默认方法
    default void start(){
        System.out.println("开始");
    }
    default void stop(){
        System.out.println("结束");
    }

    //静态方法
    static void show(){
        System.out.println("USB 3.0可以同步全速地进行读写操作");
    }
}

3.说明

在JDK8.0 之前,接口中只允许出现:

(1)公共的静态的常量:其中public static final可以省略

(2)公共的抽象的方法:其中public abstract可以省略

理解:接口是从多个相似类中抽象出来的规范,不需要提供具体实现

在JDK8.0 时,接口中允许声明默认方法静态方法

(3)公共的默认的方法:其中public 可以省略,建议保留,但是default不能省略

(4)公共的静态的方法:其中public 可以省略,建议保留,但是static不能省略

在JDK9.0 时,接口又增加了:

(5)私有方法

除此之外,接口中没有构造器,没有初始化块,因为接口中没有成员变量需要动态初始化。

4.接口的使用

(1)类实现接口(implements)

①定义

        接口不能创建对象,但是可以被类实现(implements ,类似于被继承)。

        类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements关键字。

②格式

【修饰符】 class 实现类  implements 接口{
    // 重写接口中抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
      // 重写接口中默认方法【可选】
}

【修饰符】 class 实现类 extends 父类 implements 接口{
    // 重写接口中抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
      // 重写接口中默认方法【可选】
}

③注意
  • 如果接口的实现类是非抽象类,那么必须重写接口中所有抽象方法

  • 默认方法可以选择保留,也可以重写。

    重写时,default单词就不要再写了,它只用于在接口中表示默认方法,到类中就没有默认方法的概念了

  • 接口中的静态方法不能被继承也不能被重写

④举例
interface Appliance {
    public void turnOn();
    public void turnOff();
}

class Home {
    public static void operate(Appliance appliance) {
        appliance.turnOn();
        System.out.println("=========== 家用电器正在工作 ========");
        appliance.turnOff();
    }
}

class Light implements Appliance {
    public void turnOn() { // 重写方法
        System.out.println("灯光打开。");
    }
    public void turnOff() { // 重写方法
        System.out.println("灯光关闭。");
    }
}

class Fan implements Appliance {
    public void turnOn() { // 重写方法
        System.out.println("风扇打开。");
    }
    public void turnOff() { // 重写方法
        System.out.println("风扇关闭。");
    }
}

public class ApplianceDemo {
    public static void main(String args[]) {
        Home.operate(new Light());
        Home.operate(new Fan());

        Home.operate(new Appliance() {
            public void turnOn() {
                System.out.println("空调打开。");
            }
            public void turnOff() {
                System.out.println("空调关闭。");
            }
        });
    }
}

(2)接口的多实现(implements)

①定义

        在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。

②格式

【修饰符】 class 实现类  implements 接口1,接口2,接口3。。。{
    // 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
      // 重写接口中默认方法【可选】
}

【修饰符】 class 实现类 extends 父类 implements 接口1,接口2,接口3。。。{
    // 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
      // 重写接口中默认方法【可选】
}

③注意

        接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次

④举例
package com.myexample.devices;

public interface Screen {
    void display();
}

package com.myexample.devices;

public interface Speaker {
    void playSound();
}

package com.myexample.devices;

public class SmartDevice implements Screen, Speaker {
    @Override
    public void display() {
        System.out.println("屏幕显示内容");
    }

    @Override
    public void playSound() {
        System.out.println("通过扬声器播放声音");
    }
}

package com.myexample.devices;

public class TestDevice {
    public static void main(String[] args) {
        SmartDevice device = new SmartDevice();
        device.display();
        device.playSound();
    }
}

(3)接口的多继承(extends)

①定义

        一个接口能继承另一个或者多个接口,接口的继承也使用 extends 关键字,子接口继承父接口的方法。

②注意

        所有父接口的抽象方法都有重写。

        方法签名相同的抽象方法只需要实现一次。

③举例
package com.myexample.interfacetype;

// 父接口:定义基本连接方法
public interface Connectable {
    void connect();
    void disconnect();
    void status();
}

// 子接口:继承父接口并增加新方法
public interface Bluetooth extends Connectable {
    void pair();
}

// 无线接口:定义无线传输方法
public interface Wireless {
    void transmit();
    void receive();
}

// 实现类:实现子接口并重写所有方法
public class BluetoothSpeaker implements Bluetooth, Wireless {
    @Override
    public void pair() {
        System.out.println("设备配对成功");
    }

    @Override
    public void connect() {
        System.out.println("设备已连接");
    }

    @Override
    public void disconnect() {
        System.out.println("设备已断开连接");
    }

    @Override
    public void status() {
        System.out.println("设备状态正常");
    }

    @Override
    public void transmit() {
        System.out.println("传输数据中...");
    }

    @Override
    public void receive() {
        System.out.println("接收数据中...");
    }
}

// 测试类:测试实现类的所有方法
public class TestBluetoothSpeaker {
    public static void main(String[] args) {
        BluetoothSpeaker speaker = new BluetoothSpeaker();
        speaker.pair();         // 测试设备配对
        speaker.connect();      // 测试设备连接
        speaker.transmit();     // 测试数据传输
        speaker.receive();      // 测试数据接收
        speaker.status();       // 测试设备状态
        speaker.disconnect();   // 测试设备断开
    }
}

(4)接口与实现类对象构成多态引用

①定义

        实现类实现接口,类似于子类继承父类,因此,接口类型的变量与实现类的对象之间,也可以构成多态引用。通过接口类型的变量调用方法,最终执行的是你new的实现类对象实现的方法体。

②举例
package com.myexample.interfacetype;

// 定义USB3接口
public interface USB3 {
    void start();
    void stop();
    void in();
    void out();
}

package com.myexample.interfacetype;

// 定义Mouse实现类
public class Mouse implements USB3 {
    @Override
    public void start() {
        System.out.println("鼠标开始工作");
    }

    @Override
    public void stop() {
        System.out.println("鼠标停止工作");
    }

    @Override
    public void in() {
        System.out.println("鼠标不接收信号");
    }

    @Override
    public void out() {
        System.out.println("鼠标发送脉冲信号");
    }
}

package com.myexample.interfacetype;

// 定义KeyBoard实现类
public class KeyBoard implements USB3 {
    @Override
    public void start() {
        System.out.println("键盘开始工作");
    }

    @Override
    public void stop() {
        System.out.println("键盘停止工作");
    }

    @Override
    public void in() {
        System.out.println("键盘不接收信号");
    }

    @Override
    public void out() {
        System.out.println("键盘发送按键信号");
    }
}

package com.myexample.interfacetype;

// 定义MobileHDD实现类
public class MobileHDD implements USB3 {
    @Override
    public void start() {
        System.out.println("移动硬盘开始工作");
    }

    @Override
    public void stop() {
        System.out.println("移动硬盘停止工作");
    }

    @Override
    public void in() {
        System.out.println("移动硬盘接收数据");
    }

    @Override
    public void out() {
        System.out.println("移动硬盘输出数据");
    }
}

package com.myexample.interfacetype;

// 定义Computer类
public class Computer {
    private USB3 usb;

    public void setUsb(USB3 usb) {
        this.usb = usb;
    }
}

package com.myexample.interfacetype;

// 测试类
public class TestComputer {
    public static void main(String[] args) {
        Computer computer = new Computer();
        
        // 使用Mouse对象
        USB3 usb = new Mouse();
        computer.setUsb(usb);
        usb.start();
        usb.out();
        usb.in();
        usb.stop();
        System.out.println("--------------------------");

        // 使用KeyBoard对象
        usb = new KeyBoard();
        computer.setUsb(usb);
        usb.start();
        usb.out();
        usb.in();
        usb.stop();
        System.out.println("--------------------------");

        // 使用MobileHDD对象
        usb = new MobileHDD();
        computer.setUsb(usb);
        usb.start();
        usb.out();
        usb.in();
        usb.stop();
    }
}

(5)使用接口的静态成员

①定义

        接口不能直接创建对象,但是可以通过接口名直接调用接口的静态方法和静态常量。

②举例
package com.myexample.interfacetype;

public class TestUSB3 {
    public static void main(String[] args) {
        // 通过“接口名.”调用接口的静态方法 (JDK8.0才能开始使用)
        USB3.show();
        // 通过“接口名.”直接使用接口的静态常量
        System.out.println(USB3.MAX_SPEED);
    }
}

(6)使用接口的非静态方法

  • 对于接口的静态方法,直接使用“接口名.”进行调用即可

    • 也只能使用“接口名."进行调用,不能通过实现类的对象进行调用

  • 对于接口的抽象方法、默认方法,只能通过实现类对象才可以调用

    • 接口不能直接创建对象,只能创建实现类的对象

package com.myexample.interfacetype;

public class TestMobileHDD {
    public static void main(String[] args) {
        // 创建实现类对象
        MobileHDD b = new MobileHDD();

        // 通过实现类对象调用重写的抽象方法
        b.start();
        b.in();
        b.out();
        b.stop();

        // 通过接口名调用接口的静态方法
        USB3.show();
    }
}

 5.JDK8中相关冲突问题

(1)默认方法冲突问题

①类优先原则

        当一个类,既继承一个父类,又实现若干个接口时,父类中的成员方法与接口中的抽象方法重名,子类就近选择执行父类的成员方法。代码如下:

定义接口:

​public interface Friend {
    default void date(){//约会
        System.out.println("吃喝玩乐");
    }
}

定义父类:

public class Father {
    public void date(){//约会
        System.out.println("爸爸约吃饭");
    }
}

定义子类:

public class Son extends Father implements Friend {
    @Override
    public void date() {
        //(1)不重写默认保留父类的
        //(2)调用父类被重写的
//        super.date();
        //(3)保留父接口的
//        Friend.super.date();
        //(4)完全重写
        System.out.println("跟Theodore_1022Blog学Java");
    }
}

定义测试类:

public class TestSon {
    public static void main(String[] args) {
        Son s = new Son();
        s.date();
    }
}
②接口冲突(左右为难)
  • 当一个类同时实现了多个父接口,而多个父接口中包含方法签名相同的默认方法时,怎么办呢?

无论你多难抉择,最终都是要做出选择的。

声明接口:

public interface BoyFriend {
    default void date(){//约会
        System.out.println("神秘约会");
    }
}

选择保留其中一个,通过“接口名.super.方法名"的方法选择保留哪个接口的默认方法。

public class Girl implements Friend,BoyFriend{
​
    @Override
    public void date() {
        //(1)保留其中一个父接口的
//        Friend.super.date();
//        BoyFriend.super.date();
        //(2)完全重写
        System.out.println("跟Theodore_1022Blog学Java");
    }
​
}

测试类

public class TestGirl {
    public static void main(String[] args) {
        Girl girl = new Girl();
        girl.date();
    }
}
  • 当一个子接口同时继承了多个接口,而多个父接口中包含方法签名相同的默认方法时,怎么办呢?

另一个父接口:

public interface USB2 {
    //静态常量
    long MAX_SPEED = 60*1024*1024;//60MB/s
​
    //抽象方法
    void in();
    void out();
​
    //默认方法
    public default void start(){
        System.out.println("开始");
    }
    public default void stop(){
        System.out.println("结束");
    }
​
    //静态方法
    public static void show(){
        System.out.println("USB 2.0可以高速地进行读写操作");
    }
}

子接口:

public interface USB extends USB2,USB3 {
    @Override
    default void start() {
        System.out.println("Usb.start");
    }
​
    @Override
    default void stop() {
        System.out.println("Usb.stop");
    }
}

小贴士:

子接口重写默认方法时,default关键字可以保留。

子类重写默认方法时,default关键字不可以保留。

(2)常量冲突问题

  • 当子类继承父类又实现父接口,而父类中存在与父接口常量同名的成员变量,并且该成员变量名在子类中仍然可见。

  • 当子类同时实现多个接口,而多个接口存在相同同名常量。

此时在子类中想要引用父类或父接口的同名的常量或成员变量时,就会有冲突问题。

父类和父接口:

public class SuperClass {
    int x = 1;
}
package com.atguigu.interfacetype;
​
public interface SuperInterface {
    int x = 2;
    int y = 2;
}
package com.atguigu.interfacetype;
​
public interface MotherInterface {
    int x = 3;
}
子类:

package com.atguigu.interfacetype;
​
public class SubClass extends SuperClass implements SuperInterface,MotherInterface {
    public void method(){
//        System.out.println("x = " + x);//模糊不清
        System.out.println("super.x = " + super.x);
        System.out.println("SuperInterface.x = " + SuperInterface.x);
        System.out.println("MotherInterface.x = " + MotherInterface.x);
        System.out.println("y = " + y);//没有重名问题,可以直接访问
    }
}

总结

        本篇对JAVA基础中面向对象编程思想中的接口进行了详细描述,便于学习与应用。部分内容源自网络,如有侵权请联系作者删除,谢谢! 

  • 31
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值