欢迎来到 Kong Xiangqun 的博客

12-接口

一、接口

▪ 我们前面用继承关系,描述了动物、哺乳动物、爬行动物的各种
 关系。
▪ 现在我们要描述:
  – 飞机 导弹 子弹 篮球 石头的关系?
他们之间有继承关系吗?没有
他们的共同特征都有飞的方式
这个飞的方式我们就可以用接口来定义。
 
▪如何定义接口?
  –格式:
    ▪[访问修饰符] interface 接口名 [extends 父接口1,父接口2…] {
      –常量定义 //总是public static final
      –方法定义 //总是:public abstract
    ▪}
▪如何实现接口
  –子类通过implements来实现接口中的规范
  –接口丌能创建实例,但是可用于声明引用变量类型。
  –一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public的。
  –Java的类只支持单继承,接口支持多继承
 
例子:
▪ 要求实现防盗门的功能
  门有“开”和“关”的功能,锁有“上锁”和“开锁”的功能
  将门和锁分别定义为抽象类
/*
防盗门是一个门, 防盗门上也具有一个锁, 因此将门和锁定义为抽象类,
防盗门相当于具体的子类实现
*/
public abstract class Door {
    // 打开门
    public abstract void openDoor();
    // 关闭门
    public abstract void closeDoor();
}
public abstract class Lock {
    public abstract void openLock();
    public abstract void closeLock();
}

子类实现的时候因为java不允许多继承,  因此java中有另一种方式interface

防盗门可以继承门的同时又继承锁吗?
如何解决这个问题呢?
 
将门定义为抽象类,锁定义为接口
防盗门继承门,实现锁的接口

Lock.java

public interface Lock {

    public final int a = 200;

    void openLock();
    void closeLock();
}
public class LockDoor extends Door implements Lock{
    @Override
    public void openDoor() {
        System.out.println("开门");
    }

    @Override
    public void closeDoor() {
        System.out.println("关门");
    }

    @Override
    public void openLock() {
        System.out.println("开锁");
    }

    @Override
    public void closeLock() {
        System.out.println("关锁");
    }
}
public class TestLockDoor {
    public static void main(String[] args) {
        LockDoor lockDoor = new LockDoor();
//        Lock lock = new Lock();
        lockDoor.openDoor();
        lockDoor.openLock();
        lockDoor.closeDoor();
        lockDoor.closeLock();
    }
}

打印结果:

/*
开门
开锁
关门
关锁

Process finished with exit code 0
*/
/*
* java中的继承关系是单继承,如果拥有多个父类的时候,可以考虑使用接口进行实现
*       java中的接口具备广泛的使用:
*       用法:
*           使用interface来修饰
*           接口中可以包含多个方法,且方法跟抽象类中的抽象方法一致,可以不写实现,子类在实现的时候必须要实现代码逻辑
*           子类实现接口使用implements关键字
*       特征:
*           1、接口中的所有方法都是抽象方法,不能包含方法的实现
*           2、接口中的所有方法的访问修饰权限都是public,不写并不是默认访问权限,而是public
*           3、接口不能被实例化
*           4、接口的子类必须要实现接口中的所有方法,跟抽象类有所不同,抽象类中的抽象方法必须要被子类实现
*           5、子类可以拥有实现多个接口
*           6、接口中的变量都是静态常量,如果变量没有使用static关键字修饰,它也表示静态常量,不用final关键字修饰,也是常量
*           7、接口中的方法和常量无论是否添加public修饰,默认的权限有且仅有一个,就是public
*
*      接口的使用:
*           1、接口代表一种能力,接口中可以定义N多个方法,子类在进行实现的时候,必须要实现这些方法
*               将这些方法进行实现,就意味着具备了方法的能力
*               关心实现类有何能力,而不关心实现细节
*
* */

验证"特征 第6点"

public class TestLockDoor {
    public static void main(String[] args) {
        LockDoor lockDoor = new LockDoor();
//        Lock lock = new Lock();
        lockDoor.openDoor();
        lockDoor.openLock();
        lockDoor.closeDoor();
        lockDoor.closeLock();
        lockDoor.photo();
        System.out.println(LockDoor.a);
        LockDoor.a = 300;
    }
}

报错:

java: 无法为最终变量a分配值

 防盗门是一个门               is a 的关系

 防盗门有一个锁               has a 的关系

  -上锁

  -开锁

Door现在是一个抽象类, 其实改成接口也是可以运行的, 什么时候用抽象类什么时候用接口呢?

例子:

▪ 扩展防盗门门铃功能,主要是实现拍照存档
public interface DoorBell {
    void photo();
}
public class LockDoor extends Door implements Lock,DoorBell {
    @Override
    public void openDoor() {
        System.out.println("开门");
    }

    @Override
    public void closeDoor() {
        System.out.println("关门");
    }

    @Override
    public void openLock() {
        System.out.println("开锁");
    }

    @Override
    public void closeLock() {
        System.out.println("关锁");
    }

    @Override
    public void photo() {
        System.out.println("拍照存档");
    }

}
public class TestLockDoor {
    public static void main(String[] args) {
        LockDoor lockDoor = new LockDoor();
//        Lock lock = new Lock();
        lockDoor.openDoor();
        lockDoor.openLock();
        lockDoor.closeDoor();
        lockDoor.closeLock();
        lockDoor.photo();
        System.out.println(LockDoor.a);
//        LockDoor.a = 300;
    }
}

 

 1、接口是一种能力

例子:

▪ 用程序描述USB接口
 

 

 

 

 

当实现了这个接口,就意味着具备某种能力。接口表示一种能力

对应接口的使用1

 

public interface Usb {

    // 信息传输
    public void dataTransfer();
    public void play();
}
public class Mouse implements Usb{
    @Override
    public void dataTransfer() {
        System.out.println("鼠标来点击屏幕");
    }

    @Override
    public void play() {
        System.out.println("鼠标在自己玩");
    }
}
public class UPan implements Usb {
    @Override
    public void dataTransfer() {
        System.out.println("upan可以传输数据");
    }

    @Override
    public void play() {

    }
}
public class Test {
    public static void main(String[] args) {
        Mouse mouse = new Mouse();
        mouse.dataTransfer();
        UPan up = new UPan();
        up.dataTransfer();
    }
}

运行结果为:

/*
鼠标来点击屏幕
upan可以传输数据

Process finished with exit code 0
*/

此时有一个无论什么比如AAA, 也实现了接口

public class AAA implements Usb {
    @Override
    public void dataTransfer() {
        System.out.println("AAA 进行数据传输");
    }

    @Override
    public void play() {

    }
}
将这些方法进行实现,就意味着具备 了方法的能力
 例子
-使用接口实现手机功能
▪ 需求说明:
  – 原始的手机,可以发短信,通电话。随着发展,手机增加了功能:音频、视
     频播放、拍照、上网。
 

2、接口是一种约定

▪ 生活中,我们使用的两相电源揑座,规定了:
  – 两个接头间的额定电压
  – 两个接头间的距离
  – 接头的形状
▪ 接口是一种约定
  体现在接口名称和注释上
    有些接口只有名称
    方法的实现方式要通过注释来约定
 

3、面向接口编程

程序设计时面向接口的约定而不考虑具体实现

3.1、练习1

/*
▪ 开发打印机
    – 墨盒:彩色、黑白
    – 纸张类型:A4、B5
    – 墨盒和纸张都丌是打印机厂商提供的
    – 打印机厂商要兼容市场上的墨盒、纸张
*/

 

public interface InkBox {
    /*
    * 墨盒
    * */

    // 黑白
    public void getWriteAndBlock();

    // 彩色
    public void getColor();

}
public interface Paper {
    /*
    * 纸张
    * */
    public void getA4();
    public void getB5();
}
public class CopyMechine implements InkBox,Paper {
    @Override
    public void getWriteAndBlock() {
        System.out.println("使用黑白墨盒打印");
    }

    @Override
    public void getColor() {
        System.out.println("使用彩色墨盒打印");
    }

    @Override
    public void getA4() {
        System.out.println("使用A4纸打印");
    }

    @Override
    public void getB5() {
        System.out.println("使用B5纸打印");
    }

    public static void main(String[] args) {
        CopyMechine copyMechine = new CopyMechine();
        copyMechine.getWriteAndBlock();
        copyMechine.getA4();
    }
}

3.2、练习2

/*
▪ 训练要点:
    – 接口的基础知识
    – 理解接口表示一种约定 
▪ 需求说明:
    – 采用面向接口编程思想组装一台计算机。
    – 计算机的主要组成部分有:
        ▪ CPU
        ▪ 硬盘
        ▪ 内存
*/

 

思路:

/*
▪ 实现思路:
    – 定义CPU的接口CPU,返回CPU品牌和主频
    – 定义内存的接口EMS,返回容量。
    – 定义硬盘的接口HardDisk,返回容量。
    – 编写各组件厂商分别实现CPU、EMS、和HardDisk接口编写计
       算机类,组装计算机并显示相关信息
    – 编写测试类运行
*/

定义接口

public interface CPU {
    public static final String str = "hehe";
    // 品牌
    public String getBrand();
    // 主频
    public String getHZ();
}
public interface Memory {

    // 容量
    public String getCapacity();

}
public interface HardDisk {

    // 容量
    public String getVolumn();
}

具体子类实现

CPU

intel的cpu

public class InterCpu implements CPU {

    @Override
    public String getBrand() {
        return "inter";
    }

    @Override
    public String getHZ() {
        return "2000";
    }
}

Amd的cpu

public class AmdCpu implements CPU {


    @Override
    public String getBrand() {
        return "amd";
    }

    @Override
    public String getHZ() {
        return "1000";
    }
}

硬盘

三星

public class SXHardDisk implements HardDisk{
    @Override
    public String getVolumn() {
        return "三星";

    }
}

金士顿

public class JSDHardDisk implements HardDisk {
    @Override
    public String getVolumn() {
        return "金士顿";
    }
}

内存一样

 
computer实现接口
public class Computer implements CPU,HardDisk{

    public void show(CPU cpu,HardDisk hardDisk){
        System.out.println("计算机的组成如下:");
        System.out.println("cpu:"+cpu.getBrand()+"  ,主频是:"+cpu.getHZ());
        System.out.println("硬盘容量是:"+hardDisk.getVolumn());
    }

    @Override
    public String getBrand() {
        return null;
    }

    @Override
    public String getHZ() {
        return null;
    }

    @Override
    public String getVolumn() {
        return null;
    }
}
测试类
public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer();
        CPU cpu = new InterCpu();
        HardDisk hardDisk =  new JSDHardDisk();
        computer.show(cpu,hardDisk);
    }
}

打印结果为:

/*
计算机的组成如下:
cpu:inter  ,主频是:2000
硬盘容量是:金士顿

Process finished with exit code 0
*/
▪ 阅读代码,找出错误

 

不能有构造方法

不能对方法进行实现

修饰符不能是private

 
▪ 为什么需要接口?接口和抽象类的区别?
  – 接口就是比“抽象类”还“抽象”的“抽象类”,
/*
抽象类也好、接口也好、类也好,我们定义的时候都是由具象到抽象的过程,
在识别过程中,
抽象类里面定义的方法是不需要写方法实现的,
在抽象方法里可以写也可不写,普通方法必须要写方法实现,
在接口中,不论怎么定义,方法默认都是抽象方法,就不能包含实现
*/
     可以更加规范的对子类迚行约束。
     全面地专业地实现了:规范和具体实现的分离。
  – 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须
          能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你好人,则必须干掉坏
     人;如果你是坏人,则必须欺负好人。
  – 接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
  – 项目的具体需求是多变的,我们必须以不变应万变才能从容开发,此处的
      “不变”就是“规范”。因此,我们开发项目往往都是面向接口编程!
 
▪ 接口相关规则
  – 接口中所有方法都是抽象的。
  – 卲使没有显式的将接口中的成员用public标示,也是public访问类型的
  – 接口中变量默认用 public static final标示,所以接口中定义的变量就是全
     局静态常量。
 
public interface A {
    public void show();
}
public interface B extends A{
}

  – 可以定义一个新接口,用extends去继承一个已有的接口,如果是 B implements A 会报错 No implements clause allowed for interface

  – 可以定义一个类,用implements去实现一个接口中所有方法。
    之前的都是这样的
  – 可以定义一个抽象类,用implements去实现一个接口中部分方法
 
public  abstract class C  implements A{
//    @Override
//    public void show(){
//        System.out.println("show");
//    }
}

不重写show方法也没问题, 因为是一个抽象类,可以有实现也可以不实现, 看具体情况

 

/*
▪ C++支持多重继承,Java支持单重继承
▪ C++多重继承的危险性在于一个类可能继承了同一个方法的丌同实
  现,会导致系统崩溃。
▪ Java中,一个类只能继承一个类,但同时可以实现多个接口,既可
  以实现多重继承的效果和功能,也避免的多重继承的危险性。
▪ class Student extents Person implements Runner,Flyer
▪ {…}
▪ 注意:extends 必须位于implements乊前
*/

二、什么时候用接口, 什么时候用抽象类?

/*      抽象类和接口的区别:
*           1、抽象类中的方法可以有抽象方法,也可以有普通方法,但是接口中只能包含抽象方法
*           2、抽象类需要使用abstract关键字来修饰,而接口使用interface关键字来修饰
*           3、子类使用extends关键字来继承抽象类,使用implements来实现接口
*           4、子类继承抽象类的时候必须要实现所有的抽象方法,普通方法可以不重写,而接口中的所有方法必须实现
*           5、抽象类中可以定义成员变量,而接口中只能定义静态常量
*           6、抽象类在子类实现的时候是单继承,而接口时多继承
*           7、抽象类和接口都不能实例化,但是抽象类中可以有构造方法,而接口中不能有构造方法
*           8、抽象类中可以实现接口,并且不实现接口中方法(不重写方法),而接口只能继承接口,不能实现接口
*       注意:
*           在实际的项目开发过程中,如果可以使用接口,尽量使用接口,将单继承的父类留在 
*           最关键的地方
*/

 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2022-04-25 21:11  kongxiangqun20220317  阅读(98)  评论(0编辑  收藏  举报