【JAVA学习笔记】抽象类与接口

2021-04-21  本文已影响0人  Geekero

学习自华为开发者学院陈璇老师的JAVA系列课程

一、抽象类

  1. 没有抽象构造方法,也没有抽象静态方法
  2. 抽象类中可以有非抽象的构造方法,创造子类的实例时可能调用

例如:
Base.java

//父类
public abstract class Base {
    public Base(){
        System.out.println("父类(抽象类)的构造方法");
    }
}

Son.java

//子类
public class Son extends Base{
    public Son() {
        System.out.println("子类的构造方法");
    }

    public static void main(String[] args) {
        Son son = new Son();
        Base son1 = new Son();
    }
}

输出

父类(抽象类)的构造方法
子类的构造方法
父类(抽象类)的构造方法
子类的构造方法

二、接口

2.1 JDK8之前的接口:

接口只允许有抽象的方法



JDK8之前的接口特性:



总结

MyInterface1.java

public interface MyInterface1{
    //接口不能有构造方法,也不能被实例化
    //静态常量: 接口中的变量,必须是public static final, 且要显示得初始化
    //public static final double PI = 3.14;
    //等同于
    double PI = 3.14;

    //JDK8之前,接口中只能有public abstract的方法
    public abstract void m1();

    //等同于这样声明 public abstract int m2()
    int m2();
}

MyInterface2.java

public interface MyInterface2 {
    public abstract void m3();
}

Sub1.java

//实现类必须实现接口中的全部抽象方法,除非实现类也是一个抽象类
public class Sub1 implements MyInterface1, MyInterface2 {
    public void m1() {
        System.out.println("实现类实现了接口中的m1方法");
    }

    public int m2() {
        return 0;
    }

    public void m3() {
        System.out.println("实现类实现了第二个父接口中的m3方法");
    }
}

Test.java

public class Test {
    public static void main(String[] args) {
        //接口可以当做类型来使用
        System.out.println(MyInterface1.PI);
        MyInterface1 m = new Sub1();
        m.m1();

        MyInterface2 m2 = new Sub1();
    }
}

2.1 JDK8新增的接口特性:



应用场景:



Father.java:
package cn.com.myinterface.pac2;

public abstract class Father {
    public void m5() {
        System.out.println("抽象类Father中的m5方法");
    }
}

MyInterface1.java

package cn.com.myinterface.pac2;

public interface MyInterface1 {
    //接口不能有构造方法,也不能被实例化
    //静态常量: 接口中的变量,必须是public static final, 且要显示得初始化
    //public static final double PI = 3.14;
    //等同于
    double PI = 3.14;

    //JDK8之前,接口中只能有public abstract的方法
    public abstract void m1();

    //等同于这样声明 public abstract int m2()
    int m2();

    //JDK8之后,接口中可以定义default默认方法了
    default void m3() {
        System.out.println("接口MyInterface1中的默认方法m3");
    }

    default void m5() {
        System.out.println("接口MyInterface1中的默认方法m5");
    }

    //JDK8之后,接口中可以定义static静态方法
    static void m6() {
        //等同于public static void m6()
        System.out.println("接口MyInterface1中的静态方法m6");
    }

    static void m7() {
        //等同于public static void m7()
        System.out.println("接口MyInterface1中的静态方法m7");
    }
}

MyInterface2.java

package cn.com.myinterface.pac2;

public interface MyInterface2 {
    default void m3() {
        System.out.println("接口MyInterface2中的默认方法m3");
    };
}

Sub1.java

package cn.com.myinterface.pac2;

//实现类必须实现接口中的全部抽象方法,除非实现类也是一个抽象类
public class Sub1 extends Father implements MyInterface1, MyInterface2{
    public void m1() {
        System.out.println("实现类实现了接口中的m1方法");
    }

    public int m2() {
        return 0;
    }

    /*当实现类的两个父接口中有同样的默认方法时:
    * 解决方案2:子类重写覆盖掉父接口的默认方法m3*/
    //public void m3() {
    //     System.out.println("sub类重写覆盖掉父接口的默认方法m3");
    // }

    /*当实现类的两个父接口中有同样的默认方法时:
     * 解决方案1:子类通过super指定调用哪个父接口的默认方法*/
    public void m3() {
        MyInterface1.super.m3();
    }
}

Test.java

package cn.com.myinterface.pac2;

public class Test {
    public static void main(String[] args) {
        //接口可以当做类型来使用
        //默认方法可以被继承,通过实例调用
        System.out.println(MyInterface1.PI);
        MyInterface1 m = new Sub1();
        m.m3();
        MyInterface2 m2 = new Sub1();
        m2.m3();

        Sub1 s = new Sub1();
        s.m3();

        //采用类优先的方法,优先继承抽象类中m5方法
        m.m5();
        s.m5();

        //静态方法可以被接口直接调用
        MyInterface1.m6();
    }
}

三、面向接口编程

程序设计时:

  1. 关心实现类有何能力,而不关心实现细节
  2. 面向接口的约定,而不考虑接口的具体实现

案例1
USB.java

//USB接口:描述连接计算机和外部设备的串口总线标准,定义一种输入输出接口的技术规范
public interface USB {
    //USB接口并不实现具体功能,通过抽象方法来定义一种数据输入输出规范和标准,能力
    void service();
}

USBdisk.java

//满足USB标准的U盘
public class USBdisk implements USB{
    public void service() {
        System.out.println("连接USB口,开始传输数据");
    }
}

USBfan.java

//满足USB标准的风扇
public class USBfan implements USB{
    public void service() {
        System.out.println("连接USB口,获得电流,风扇开始转动");
    }
}

Test.java

//使用接口
public class Test {
    public static void main(String[] args) {
        //USB风扇
        USB uFan = new USBfan();
        uFan.service();

        //USB标准U盘
        USB uDisk = new USBdisk();
        uDisk.service();
    }
}

总结


image.png

3.1 面向接口编程的步骤

step01.分析类和接口



step02.画类图



进行类的设计

step04.转换为代码
Door.java

//门:抽象方法 开门 关门
public abstract class Door {
    public abstract void open();
    public abstract void close();
}

DoorBell.java

//门铃:拍照存储
public interface DoorBell {
    void takePictures();
}

Lock.java

//锁:开锁 上锁
public interface Lock {
    void lockUp();
    void openlock();
}

TheftproofDoor.java

//防盗门:是门(is a),具备所得功能(has a)
public class TheftproofDoor extends Door implements Lock, DoorBell{

    //开门
    public void open() {
        System.out.println("用力推,门打开了");
    }

    //关门
    public void close() {
        System.out.println("轻轻拉门,门关上了");
    }

    //上锁
    public void lockUp() {
        System.out.println("插进钥匙,向左转3圈,锁上了,拔出钥匙");
    }

    //开锁
    public void openlock() {
        System.out.println("插进钥匙,向右转3圈,锁开了,拔出钥匙");
    }

    //按门铃拍照存储
    public void takePictures() {
        System.out.println("铃铃铃...咔嚓......拍照存储");
    }
}

Test.java

//测试防盗门功能
public class Test {
    public static void main(String[] args) {
        TheftproofDoor door = new TheftproofDoor();
        //关门上锁
        door.close();
        door.lockUp();
        //有客人拜访
        door.takePictures();
        //开锁开开门
        door.openlock();
        door.open();
    }
}

3.2 抽象类 VS 接口



Phone.java

//抽象类:手机类
public abstract class Phone {
    private String  brand; //品牌
    private String type; //型号

    public Phone(){};

    public Phone(String brand, String type) {
        this.brand = brand;
        this.type = type;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    //输出手机信息
    public void showInfo() {
        System.out.println("这是一台"+brand+type+"手机。");
    }
    //打电话
    public abstract void call();

    //发信息
    public abstract void sendMsg();
}

NetWork.java:

//接口:上网能力
public interface NetWork {
    void networkConn();
}

PlaySth.java

//接口:播放能力
public interface PlaySth {
    void play(String content);
}

TakePhone.java

//接口:拍照能力
public interface TakePhone {
    void takePhotos();
}

CommonPhone.java

//原始的普通手机,是手机, 只具备播放能力
public class CommonPhone extends Phone implements PlaySth {
    public CommonPhone(){}
    public CommonPhone(String brand, String type) {
        super(brand, type);
    }

    //打电话
    public void call() {
        System.out.println("正在语言通话中......");
    }

    //发信息
    public void sendMsg() {
        System.out.println("正在发送文字信息......");
    }

    //只能播放音频
    public void play(String content) {
        System.out.println("正在播放音频《"+content+"》......");
    }
}

SmartPhone.java

//智能手机:是手机, 且具备上网、拍照、播放能力
public class SmartPhone extends Phone implements NetWork, TakePhone, PlaySth{
    public SmartPhone(){}
    public SmartPhone(String brand, String type) {
        super(brand, type);
    }

    //上网
    public void networkConn() {
        System.out.println("连接上了WIFI网络.......");
    }

    //打电话
    public void call() {
        System.out.println("正在视频通话中.....");
    }

    //发信息
    public void sendMsg() {
        System.out.println("正在发送文字+图片+音频的信息......");
    }

    public void play(String content) {
        System.out.println("正在播放视频《"+content+"》......");
    }

    //拍照
    public void takePhotos() {
        System.out.println("卡擦,拍了一张美图......");
    }
}

Test.java

//测试类:
public class Test {
    public static void main(String[] args) {
        CommonPhone phone1 = new CommonPhone("诺基亚", "T5");
        phone1.sendMsg();
        phone1.call();
        phone1.play("慢慢喜欢你");

        System.out.println("*********************************");
        SmartPhone phone2 = new SmartPhone("Iphone", "XS Max");
        phone2.sendMsg();
        phone2.play("哪吒");
        phone2.takePhotos();
    }
}

3.3 接口小结

接口的作用

  1. 提高程序的可维护性和可扩展性
  2. 提高程序的规范性
  3. 提高程序的安全类

案例3:打印机

InkBox.java
//接口:代表了生产墨盒的标准或约定,可以认为是墨盒的行业生产标准
public interface InkBox {
    //得到墨盒的颜色
    String getColor();
}

Paper.java

//接口:代表了生产纸张的标准或约定,可以认为是纸张的行业生产标准
public interface Paper {
    //得到纸张大小
    String getSize();
}

ColorInkBox.java

//彩色墨盒
public class ColorInkBox implements InkBox{

    //墨盒颜色
    public String getColor() {
        return "彩色";
    }
}

WhiteBlackInkBox.java

public class WhiteBlackInkBox implements InkBox{


    //墨盒颜色
    public String getColor() {
        return "黑白";
    }
}

A4Paper.java

//生产A4纸张
public class A4Paper implements Paper {

    public String getSize() {
        return "A4";
    }
}

B5Paper.java

public class B5Paper implements Paper{

    public String getSize() {
        return "B4";
    }
}

Printer.java

//打印机类
public class Printer {
    //墨盒 纸张  作为成员变量出现
    InkBox inkbox;
    Paper paper;

    //安装墨盒
    public void setInkbox(InkBox inkbox) {
        this.inkbox = inkbox;
    }

    //往打印机中放纸
    public void setPaper(Paper paper) {
        this.paper = paper;
    }

    //使用墨盒在纸张上打印
    public void print() {
        System.out.println("使用"+inkbox.getColor()+"的墨盒,在"+paper.getSize()+"的纸上打印");
    }
}

Test.java

//测试类
public class Test {
    public static void main(String[] args) {
        //买一台打印机
        Printer printer = new Printer();
        InkBox inkbox = null;
        Paper paper = null;
        //彩色打印A4纸
        inkbox = new ColorInkBox();
        paper = new A4Paper();
        printer.setInkbox(inkbox);
        printer.setPaper(paper);
        printer.print();

        //黑白打印B5纸
        inkbox = new WhiteBlackInkBox();
        paper = new B5Paper();
        printer.setInkbox(inkbox);
        printer.setPaper(paper);
        printer.print();
    }
}

案例4:组装电脑



CPU.java

public interface CPU {
    String getBrand();
    String getFrequency();
}

EMS.java

public interface EMS {
    String getType();
    String getStroage();
}

HardDisk.java

public interface HardDisk {
    String getStorage();
}

IntelCPU.java

public class IntelCPU implements CPU {
    @Override
    public String getBrand() {
        return "Intel";
    }

    @Override
    public String getFrequency() {
        return "3.8GHz";
    }
}

RAM.java

public class RAM implements EMS{
    @Override
    public String getType() {
        return "DDR4";
    }

    @Override
    public String getStroage() {
        return "4GB";
    }
}

HDD.java

public class HDD implements HardDisk{

    @Override
    public String getStorage() {
        return "3000GB";
    }
}

Computer.java

public class Computer {
    //CPU EMS HardDisk 作为成员变量出现
    CPU cpu;
    EMS ems;
    HardDisk hardDisk;

    //组装电脑
    public void setCPU(CPU cpu) {
        this.cpu = cpu;
    }

    public void setEMS(EMS ems) {
        this.ems = ems;
    }

    public void setHardDisk(HardDisk hardDisk) {
        this.hardDisk = hardDisk;
    }

    //打印信息
    public void showInfo() {
        System.out.println("CPU的品牌是:"+cpu.getBrand()+",主频是:"+cpu.getFrequency());
        System.out.println("硬盘容量是:"+hardDisk.getStorage());
        System.out.println("内存类型是:"+ems.getStroage()+",内存容量是:4GB");
    }
}

Test.java

public class Test {
    public static void main(String[] args) {
        //购买电脑
        Computer computer = new Computer();
        CPU cpu;
        EMS ems;
        HardDisk hardDisk;

        //组装
        cpu = new IntelCPU();
        ems = new RAM();
        hardDisk = new HDD();

        computer.setCPU(cpu);
        computer.setEMS(ems);
        computer.setHardDisk(hardDisk);

        //显示信息
        computer.showInfo();
    }
}
上一篇下一篇

猜你喜欢

热点阅读