【Java SE】抽象类和接口

🥰🥰🥰来都来了,不妨点个关注叭!
👉博客主页:欢迎各位大佬!👈

在这里插入图片描述

1. 抽象类

1.1 抽象类是什么

在之前讲解的多态中,基于多态编写出打印多个形状的代码案例,我们一起来回顾一下~

public class Shape {
    public void draw() {
        System.out.println("画图形~");
    }
}
public class Rectangle extends Shape{
    @Override
    public void draw() {
        System.out.println("◇");
    }
}
public class Cycle extends Shape{
    @Override
    public void draw() {
        System.out.println("○");
    }
}

public class Fish extends Shape{
    @Override
    public void draw() {
        System.out.println("🐟");
    }
}
public class Test3 {
    public static void drawShapes1() {
        Shape[] shapes = {new Cycle(),new Rectangle(),new Fish()};
        for(Shape x: shapes) {
            x.draw();
        }
    }

    public static void main(String[] args) {
        drawShapes1();
    }
}

在打印图形这个例子中可以看到,Shape是父类,打印各种类型为子类,重写父类draw的方法,发现父类 Shape 中的 draw 方法没有什么实际工作,没有描述一个具体的图形,其draw方法无法具体实现,主要的绘制图形都是由Shape的各种子类的draw方法来完成,像这种没有实际工作的方法,可以把它设计成一个抽象方法,包含抽象方法的类即称为抽象类
在这里插入图片描述
还有很多这样的栗子,比如车都可以在路上跑起来(run),但是什么类型的车呢,以什么样的方式跑呢~对于不同类型的车有不同的结果,自行车需要人踩踏板前行,电瓶车需要电瓶发电骑行,小汽车需要发动机启动等等,即可以把车表达为抽象类,对于不同类型的车,可重写父类车的run方法
抽象类】是一个特殊的类,包含抽象方法,它不能被实例化,即不能创建抽象类的对象

1.2 抽象类的意义

抽象类作为其他类的基类,如要使用,只能创建该抽象类的子类,子类重写抽象类的抽象类方法,使用抽象类相当于多了一重编译器的校验
(使用抽象类场景如下面代码,实际工作不应该由父类完成,而由子类完成,如果不小心误用父类了,则使用普通父类编译器不会报错,但父类是抽象类,就会在实例化的时候提示错误,可以让我们尽早发现问题)

1.3 抽象类的语法

在Java中,表示抽象类,需借助abstract关键字,具体语法如下:

//抽象类
public abstract class Shape {
    //抽象方法,被abstract修饰,没有方法体
    abstract public void draw();
    abstract public void calculateArea();
    
    //抽象类可以增加普通方法和属性
    public double area; //图形面积`在这里插入代码片`
    
    public double getArea() {
        return area;
    }
}

注意事项】抽象类也是类,只是比较特殊,无法实例化对象,内部可以包含普通属性和方法甚至构造方法
上述的描述图形的栗子,将父类Shape编写为抽象类如上述代码,各子类代码如下:

public class Rectangle extends Shape {
    @Override
    public void draw() {
        System.out.println("◇");
    }

    double width = 1.2;
    double length = 1.4;

    @Override
    public void calculateArea() {
        area = width * length;
    }
}
public class Cycle extends Shape{
    double r = 4.0;

    @Override
    public void calculateArea() {
        area = 3.14*r*r;
    }

    @Override
    public void draw() {
            System.out.println("○");
        }
    }
public class Fish extends Shape{
    @Override
    public void calculateArea() {
        System.out.println("不好计算~");
    }

    @Override
    public void draw() {
        System.out.println("🐟");
    }
}
public class Test {
    public static void drawShapes1() {
        Shape[] shapes = {new Cycle(),new Rectangle(),new Fish()};
        for(Shape x: shapes) {
            x.draw();
        }
    }

    public static void main(String[] args) {
        drawShapes1();

    }
}

1.4 抽象类的特性

(1) 抽象类不能直接实例化对象
(2) 抽象方法不能被private访问权限修饰符修饰
(3) 抽象类必须被继承,并且继承后子类要重写父类中的所有抽象方法,否则子类也是抽象类,必须要使用 abstract修饰
(4) 抽象方法不能被final和static修饰,抽象方法要被子类重写,如果被final或者static则无法重写
(5) 抽象类中不一定包含抽象方法,抽象类中可以没有抽象方法,但有抽象方法的类一定是抽象类
(6) 抽象类中可以有构造方法,在子类创建对象时,初始化父类的成员变量

2. 接口

2.1 接口是什么

在生活中,我们随处可见接口的栗子,如电脑的USB口,电源插座插孔等等
电脑的USB口可以插U盘、鼠标等所有符合USB协议的设备
电源插座插孔可以插电脑、电视机等所有符合规范的设备
通过上述例子可以看出:
接口】公共的行为规范标准,在实现时,只要符合规范标准,即可以通用,在Java中,接口可以看作成是多个类的公共规范,是一种引用数据类型

2.2 接口的意义

可以进行统一访问,并且可以多接口,在某种程度上实现多继承,定义一个接口可以有多个实现,可扩展性强~

2.3 接口的语法

接口的定义方式与类的定义方式很相似,需要运用interface关键字来定义接口,接口中每一个方法都是由public修饰的抽象方法,即接口中的方法会被隐式的指定为public abstract,即在方法前不写,也是public abstract修饰~

public inteferface 接口名称 {
//抽象方法
}

public interface Is {
    public abstract void method1();
    public  void method2(); // public abstract void method2();
    abstract void method3(); // public abstract void method3();
    void method4(); //更推荐该写法,保持了代码的简洁性 public abstract void method4();
}

注意
命名规则:创建接口时,接口的命名一般以大写字母 I 开头,且一般使用 “形容词” 词性的单词

2.4 接口的使用

使用】接口不能直接使用,必须要有一个实现类实现该接口,实现接口中的所有抽象方法
举例】 以下代码实现电脑使用USB鼠标和键盘为栗子~功能如下:

USB接口包含打开设备、关闭设备
笔记本类:包含开机功能、关机功能、使用USB功能
鼠标类:实现USB接口,有点击功能
键盘类:实现USB接口,输入功能

public interface USB {
    void openDevice();
    void closeDevice();
}
//鼠标类实现USB接口
public class Mouse implements USB{
    //重写接口中的抽象方法
    @Override
    public void openDevice() {
        System.out.println("打开鼠标");
    }

    @Override
    public void closeDevice() {
        System.out.println("关闭鼠标");
    }

    public void click() {
        System.out.println("点击鼠标");
    }
}
public class KeyBoard implements USB{
    //重写接口中的抽象方法
    @Override
    public void openDevice() {
        System.out.println("打开键盘");
    }

    @Override
    public void closeDevice() {
        System.out.println("关闭键盘");
    }

    public void inPut() {
        System.out.println("键盘输入");
    }
}
public class Computer {
    public void powerOn() {
        System.out.println("打开笔记本电脑");
    }

    public void powerOff() {
        System.out.println("关闭笔记本电脑");
    }

    public void useDevice(USB usb) {
    //统一打开设备
        usb.openDevice();
        //向下转型
        if(usb instanceof Mouse) {
            Mouse mouse = (Mouse)usb;
            mouse.click();
        }else if(usb instanceof KeyBoard) {
            KeyBoard keyBoard = (KeyBoard)usb;
            keyBoard.inPut();
        }
     //统一关闭设备
        usb.closeDevice();
    //由打印结果可以看出接口好处
    }
}
public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.powerOn();

        //使用鼠标
        computer.useDevice(new Mouse());

        //使用键盘
        computer.useDevice(new KeyBoard());

        computer.powerOff();
    }
}

在这里插入图片描述

2.5 接口的特性

(1) 接口类型是一种引用类型,但不能直接new接口对象
(2) 接口中的每一个方法均为public abstract,即接口方法会被隐式的指定为public abstract(且只能是这个)
(3) 接口中的方法不能在接口中实现,必须要由实现接口的类来实现
(4) 重写接口中的方法不能使用默认default的访问权限(因为接口中的默认是public权限,不能比它更低,即重写方法前面需加public),即子类的访问修饰权限一定要大于等于父类的访问权限
(5) 接口中可以含有变量,但是接口中的变量会被隐式的指定为public static final变量
(6) 接口中不能有静态代码块和构造方法
(7) 接口虽不是类,但接口编译完成后字节码文件的后缀格式也是**.class**
(8) 如果类没有实现接口中的全部抽象方法,则类必须设置为抽象类,即该实现类必须实现接口中的所有方法,否则得设置为抽象类
(9) jdk8中接口中还可以包含default方法

2.6 实现多个接口

在之前学习的继承中,我们知道Java不支持多继承,即一个类继承多个类,但在接口中,可以实现一个类多个接口
1)先通过父类Animal表示一组动物
2)创建三个接口,分别为会跑、会游、会飞
3)创建具体的动物类并实现接口中方法,狗是一种动物会跑,鱼是一种动物会游,青蛙是一种动物会跑会游,鸭子是一种动物会跑、游和飞
4)实现一个方法walk()散步,在该方法内部无需关注是哪一个类型,只要具备跑的特性~

public class Animal {
    protected String name;

    public Animal(String name) {
        this.name = name;
    }
}
public interface IRunning {
    void run();
}

public interface ISwimming {
    void swim();
}
public class Dog extends Animal implements IRunning{
    public Dog(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println(this.name+"四条腿在跑~");
    }
}
public class Fish extends Animal implements ISwimming{
    public Fish(String name) {
        super(name);
    }

    @Override
    public void swim() {
        System.out.println(this.name+"正在水里游~");
    }
}
//青蛙又可在陆地也可以在水里~
public class Frog extends Animal implements IRunning,ISwimming{
    public Frog(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println(this.name+"在地上跳~");
    }

    @Override
    public void swim() {
        System.out.println(this.name+"在水里蹬~");
    }
}
//鸭子又可以跑又可以在水里游还能飞~
public class Duck extends Animal implements  IRunning,ISwimming,IFlying {
    public Duck(String name) {
        super(name);
    }

    @Override
    public void run() {
        System.out.println(this.name + "在地上跑~");
    }

    @Override
    public void swim() {
        System.out.println(this.name + "在水里浮着~");
    }

    @Override
    public void fly() {
        System.out.println(this.name + "在低空中挥动翅膀~");
    }
}
public class Test1 {
    public static void walk(IRunning running) {
        System.out.println("一起去散步!");
        running.run();
    }
    public static void main(String[] args) {
        Dog dog = new Dog("小狗");
        walk(dog);

        Frog frog = new Frog("小青蛙");
        walk(frog);
    }
}

在这里插入图片描述
优点
上面的代码展示Java面向对象编程中最常见的用法:一个类继承一个父类,同时实现多种接口
继承表达的含义是 is - a ,而接口表达的含义是具有什么特性,比如狗, 继承父类Animal,表示狗是一种动物,实现接口IRunning,表示狗具有跑的特性~多态的好处,就是让程序猿忘记类型,有接口后,类的使用者就不必关注具体类型而只关注某个类是否具备某种能力或某种特性

2.7 接口间的继承

接口间继承相当于把多个接口合并在一起,在Java中,类和类之间无法多继承,但一个类可以实现多个接口,接口与接口之间可以多继承,即用接口可以达到多继承目的

interface IRunning {
    void run();
}

interface ISwimming {
    void swim();
}

interface IFlying {
    void fly();
}

//三栖动物既可以在陆地生活也可以在水中空中
interface Itrixenie extends IRunning,IFlying,ISwimming {
    
}

//蜥蜴是三栖动物,既可以跑,也可飞,也能在水里生活
class lizard implements Itrixenie {
    ...    
    //需要实现run、swim、fly三个抽象方法
}

通过接口继承创建一个新的接口Itrixenie 表示三栖的,此时实现接口创建的lizard类, 继续要实现run方法,也需要实现swim方法,还需要实现fly方法
💛💛💛本期内容回顾💛💛💛
在这里插入图片描述
✨✨✨本期内容到此结束啦~下期再见!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值