• 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、抽象类中可以实现接口,并且不实现接口中方法(不重写方法),而接口只能继承接口,不能实现接口
    *       注意:
    *           在实际的项目开发过程中,如果可以使用接口,尽量使用接口,将单继承的父类留在 
    *           最关键的地方
    */
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    BZOJ4779: [Usaco2017 Open]Bovine Genomics
    USACO比赛题泛刷
    BZOJ1977: [BeiJing2010组队]次小生成树 Tree
    LOJ #10132. 「一本通 4.4 例 3」异象石
    $O(n+log(mod))$求乘法逆元的方法
    BZOJ2226: [Spoj 5971] LCMSum
    数据库 | Redis 缓存雪崩解决方案
    中间件 | 微服务架构
    数据库 | SQL 诊断优化套路包,套路用的对,速度升百倍
    数据库 | SQL语法优化方法及实例详解
  • 原文地址:https://www.cnblogs.com/kongxiangqun/p/15743070.html
Copyright © 2020-2023  润新知