【Java】一篇文章彻底吃透抽象类和接口 |超详细,建议收藏

在这里插入图片描述

  • 博主简介:努力学习的预备程序媛一枚~
  • 博主主页: @是瑶瑶子啦
  • 所属专栏: Java岛冒险记【从小白到大佬之路】

文章目录

  • 一、抽象类
    • 1.1:抽象类的概念
    • 1.2:抽象类的定义
    • 1.3:抽象类的特性
    • 1.4:抽象类的作用和意义
  • 二、接口
    • 引入
    • 2.1、简介
    • 2.2、接口的定义
      • 2.2.1:接口内部语法
    • 2.3、接口的实现
      • 2.3.1:普通类实现接口
      • 2.3.2:抽象类实现接口
    • 2.4、接口的多态
    • 2.5、接口之间继承
    • 2.6、接口使用场景
    • 2.7、接口的特性(使用细节)
    • 2.8:接口存在的意义
  • 三、抽象类和接口的区别和联系

一、抽象类

【Java】一篇文章彻底吃透抽象类和接口 |超详细,建议收藏_第1张图片

1.1:抽象类的概念

 我们知道,可以通过类实例化一个对象。为什么呢?因为我们可以通过这个类中的属性和方法具体描述这个对象

 但是,不是所有的类都可以具体描述一个对象

‍♀️何为 “具体描述” ???
看下面这个例子:

class Shape {
    public void draw() {

    }

    public void getArea() {

    }

    protected double area;
}

//矩形类
class Rect extends Shape {
    private final double length;
    private final double width;

    public Rect(double length, double width) {
        this.length = length;
        this.width = width;
    }

    @Override
    public void draw() {
        System.out.println("矩形:length = " + length + "width = " + width);
    }

    @Override
    public void getArea() {
        area = length * width;
    }
}

//圆形类
class Circle extends Shape {
    private final double r;
    final private double PI = 3.14;

    public Circle(double r) {
        this.r = r;
    }

    @Override
    public void draw() {
        System.out.println("圆形:半径r = " + r);
    }

    @Override
    public void getArea() {
        area = PI * r * r;
    }
}

public class Main {
    public static void main(String[] args) {

    }
}

【Java】一篇文章彻底吃透抽象类和接口 |超详细,建议收藏_第2张图片

很明显,Shape类不能具体的描述一个对象(长?宽?面积?),不能将它实例化。像这样抽象的类,我们要定义成抽象类

接下来我们看看抽象类的定义:

1.2:抽象类的定义

  • 抽象类要被abstract修饰
  • 抽象类中的抽象方法(没有方法体的)也要被abstract修饰
  • 抽象类的本质也是类,可以像普通类一样有普通方法和属性
abstract class Shape {
    abstract public void draw();
    protected double area;

    public double getArea() {
        return area;
    }
}

1.3:抽象类的特性

  1. 抽象类不能直接实例化对象
  2. 抽象类的本质也是类,可以拥有成员方法&成员变量
  3. 抽象方法不能为private,且不能被finalstatic修饰,因为子类必须要重写父类中的抽象方法
  4. 抽象类被继承有两种情况
    • 子类重写该抽象类中的所有抽象方法,该类和普通类则一样,可以被实例化
    • 子类重写该抽象类中的部分抽象方法,则该类仍然是一个抽象类,无法被实例化,且必须被 abstract修饰
  5. 抽象类中可以有构造方法,作用是:子类创建对象时调用父类构造方法来初始化父类的成员变量
  6. 抽象类中不一定包含抽象方法,但是有抽象方法的一定是抽象类

1.4:抽象类的作用和意义

    ‍♀️有的人可能会想,抽象类存在的意义是什么呢?就像开头给出的那段代码那段例子,我们的确无法写出Shape类中的getArea那两个方法的方法体,那我们就空着不久行啦?为什么还要这么麻烦,定义抽象类和抽象方法呢???

    引入抽象类,其实是Java提供一种语法工具,作用是引导和规范使用者正确的使用她们,减少误用。

    使用抽象类,类使用者在创建对象时,就不会误用不完整的抽象父类实例化进行实例化(编译器会报错),就知道必须使用某个具体的子类来进行实例化。且子类继承是,就要求必须实习其抽象方法,而不可能忽略。

二、接口

【Java】一篇文章彻底吃透抽象类和接口 |超详细,建议收藏_第3张图片

引入

对于类,是具体事物抽象而成。类的概念强调类型。但是在解决问题的大多数情况下,我们并不强求一定需要某个类型。为什么这么说呢?

比如我们现在的需求是:拍照。那我们可以用手机、相机…只要能满足拍照功能的即可,我们不在意是什么类型,而是在意此事物是否有此功能,有就来

在很多情况下就是如此,类型不重要,重要的是能力

Java中用一种扩展类-----接口(interface)显现能力。今天,瑶瑶子带大家系统学习一下Java中的接口。

2.1、简介

简单来说,接口就是声明一组能力的类。接口内部声明了很多方法(一般是抽象),也就是功能,但接口本身不去做实现(每个类型的实现方法本就不同,没有必要去实现)。当 实现(implements) 了该接口,就证明这个类,拥有了该接口中声明的方法(即能力)。这样,就达到了表示能力的目的。

2.2、接口的定义

接口的定义,和类的定义十分相似:

interface SendMessage {
    public static final String MSG = "yaoyao";

    public abstract void print();
}

1. 使用interface关键字来定义一个接口(与类的定义对比:将class换成了interface)
2. 接口的修饰符只能是public默认,这点和普通类是一样的
3. 接口命名,一般以大写字母I开头
4. 接口命名一般以形容词词性单词(表示能力嘛~

2.2.1:接口内部语法

和类相似,接口内部也可定义属性和方法。但对于属性和方法的声明定义,有一定的语法规则。

  • 属性
    • public static final 变量类型 变量名
      前三个关键字可省略不写,默认就是它们;注意,因为是常量,所以接口中的属性必须显示初始化
  • 方法
    • JDK8以前:public abstract 返回类型 方法名();
      前两个关键字可省略
    • JDK 8以后: 新增了两种可以有方法体的方法:
      • 默认方法: default public 修饰;
        默认方法必须有默认的方法实现.实现接口的子类可以选择重写,也可以选择不重写.(该方法存在的意义在于:便于给接口增加功能,而又不影响子类,否则增加一个默认为抽象的方法,子类必须重写,这样封装性不好,耦合性也高)
      • 静态方法: public static 修饰
        可以直接使用接口名.方法名(参数列表)调用

阿里编程规范中,接口的属性和方法不要加任何修饰符(因为上面说了,默认就有的,可以省略

2.3、接口的实现

    上面提到,接口的本身其实就是声明一些功能,单单有接口,这不是接口设计的初衷.

    接口设计的初衷就是将接口也和类一样,作为一个Subtype(超类),供其他类去实现(拥有功能).

    接口不能实例化,必须有一个“实现类”来实现接口,实现接口中的所有抽象方法。

那如何去实现接口呢?

2.3.1:普通类实现接口

eg:Computer类实现SendMessage接口和MyCompare接口

interface SendMessage {
    public static final String MSG = "yaoyao";

    public abstract void print();
}
interface MyCompare {
	public int compare (Object otherObj);
}
class Computer implements SendMessage, MyCompare {
    String useName;
    int innerStorage;

    @Override
    public void print() {
        System.out.println(this.useName + "正在发送信息:" + MSG);
    }

    @Override
    public int compare(Object otherObj) {
        if (!(otherObj instanceof Computer)) {
            throw new IllegalArgumentException();
        }
        Computer otherCom = (Computer) otherObj;
        return this.innerStorage - otherCom.innerStorage;
    }
}

代码解释如下:

  • implements表示实现某个接口.前面是子类名,后面是要实现的接口的接口名

  • 一个子类可以实现多个接口,接口名之间用英文逗号,分隔

  • 普通类实现接口,在该类中必须全部重写实现的接口中定义的抽象方法

2.3.2:抽象类实现接口

一般来说,是普通类实现接口比较常见,但是由于普通类实现接口必须必须重写接口中所有抽象方法,这样在一些情况下会造成代码冗余.

由此,抽象类来实现接口就可以很好的解决这一问题,因为抽象类可以选择性的实现接口中的抽象方法.——实现接口中的部分抽象方法

这样一来,可以让抽象类来实现一部分常用的方法,剩下一部分让子类自己实现,来简化书写.
(ps:但是继承了一个类,就不能继承其他类了,这又是基于Java单继承模式的让普通类继承抽象类的弊端)

2.4、接口的多态

一个类的父类和这个类实现的所有接口都称为超类型(Supertype),而这个类称为该超类型的子类型(Subtype).

子类型对象的引用,可以被超类型引用变量接收,这就是对象的多态性!

和之前在多态那篇文章【Java】弄清多态,看这一篇就够了|由浅入深,保姆级详解中几乎差不多,只是那里是以普通类的父类为例,讲的多态,这里是接口.这里也就不重复造轮子了.

主要就是:

  • 接口类型引用可以指向实现接口的子类型对象
Interface A{
}
class B implements A {
}
Interface interface = new B();

这里再讲一点不同的:多态传递:接口可以继承接口,父接口的引用也可以指向实现子接口的普通类的对象.

public class Demo {
    public static void main(String[] args) {
        B b = new Son();
        A a = new Son();//OK!
    }
}

interface A {
}

interface B extends A {
}

class Son implements B {

}

    ‍♂️接口多态的意义: 让程序员“忘记”类型。类的使用者就不用关注具体类型,而只关注某个类是否具有某种功能!

2.5、接口之间继承

在上面我讲到,接口可以继承接口,这和类的继承是相似的。有以下需要注意的点:

  • 不存在子接口内实现父接口中抽象方法的说法(上面已经讲到,作为接口,其中包含的方法只有那么几种)
  • 若非抽象子类只是实现了父接口,只用重写父接口中的抽象方法
  • 若非抽象子类实现了子接口,父接口中和子接口中的抽象方法都必须被实现
  • 和类不同的是,一个接口可以继承多个父接口,中间用英文逗号分隔即可
  • 父接口的引用也可以指向实现子接口的普通类的对象(多态
//一个接口可以继承多个父接口举例:
Interface A{
	void method01();
}
Interface B{
	void method02();
}
Interface C extends A,B {
}

其实于其叫作接口的继承,不如取extends本身意思,“扩展”.即接口的扩展。时B接口同时扩展了A接口中的功能。

意义

  • 代码复用
  • 扩展功能
  • 解耦

2.6、接口使用场景

当我们,只关心实现功能时(需要实现的功能已经确定),具体用什么类型来实现,并不想具体去操心

以下是利用接口和接口多态的一个小案例:模拟数据库的连接
体会接口的好处

数据库接口:

//src.com.yaoyao
package com.yaoyao;

public interface DBInterface {
    public void connect();
    public void close();
}

不同的数据库子类:MysqlDB\OracleDB

package com.yaoyao;

public class MysqlDB implements DBInterface{
    @Override
    public void connect() {
        System.out.println("连接Mysql数据库");
    }

    @Override
    public void close() {
        System.out.println("关闭Mysql数据库连接");
    }
}

package com.yaoyao;

public class OracleDB implements DBInterface{
    @Override
    public void connect() {
        System.out.println("连接Oracle数据库");
    }

    @Override
    public void close() {
        System.out.println("关闭Oracle数据库连接");
    }
}

使用接口作为参数设计(多态的体现—>解耦)

解释:这样,fun函数的功能就是连接和关闭数据库,只要具备该功能(即实现了DBInterface接口),就可以传进来

package com.yaoyao;

public class InterfaceDemo {
    public static void main(String[] args) {
        MysqlDB mysqlDB = new MysqlDB();
        fun(mysqlDB);
    }
    public static void fun(DBInterface db){
        db.connect();
        db.close();
    }
}

2.7、接口的特性(使用细节)

这里就官方给出的解释基础上,还添加汇总一些接口使用细节和注意事项

An interface declaration defines a new interface that can ①be implemented by one or more classes. Programs can use interfaces to ②provide a common supertype for otherwise unrelated classes, and to ③make it unnecessary for related classes to share a common abstract superclass.
Interfaces ④have no instance variables, and ⑤typically declare one or more abstract methods; ⑥otherwise unrelated classes can implement an interface by providing implementations for its abstract methods. Interfaces may not be directly instantiated.

  • ①一个接口可以被多个类实现(同时,一个类也可以实现多个接口)

  • ②接口的作用相当于给没有关系的类,提供了一个超类型
    理解:比如相机、手机,没有很必然的关系,但是它们都实现了拍照这个接口,它们都具有拍照的功能。这个拍照接口,类似于是它们的超类型(superType)。注意,这里不是is-a的那个父类。你不能说手机是拍照把?

  • ③接口的实现,让相关类不必再共享同一个抽象超类

  • ④ 接口不可被实例化

  • ⑤接口中通常声明一个或多个抽象方法

  • ⑥无关的类们可以通过实现接口中的抽象方法来实现接口

  • ⑦接口不可继承普通类,但接口可继承接口

  • ⑧接口本身就是抽象的,所以可以被abstract修饰

2.8:接口存在的意义

类的使用者就不用关注具体类型,而只关注某个类是否具有某种功能!

三、抽象类和接口的区别和联系

区别 抽象类(abstract) 接口(interface)
1 结构组成 普通类+抽象方法 全局常量+抽象方法+默认方法+ 静态方法
2 子类使用 使用extends关键字,继承抽象类 使用implements关键字实现接口
3 关系 一个抽象类可以实现若干接口 接口不能继承抽象类,但是接口可以使用extends扩展多个接口
4 子类限制 一个子类只能继承一个抽象类 一个类可以实现多个接口

    抽象类和接口配合而非替代的关系。一个类通常有一个抽象类,该抽象类提供默认实现,实现全部或部分方法;可以实现多个接口,表示有多种功能!


在这里插入图片描述

  • Java岛冒险记【从小白到大佬之路】

  • LeetCode每日一题–进击大厂

  • Go语言核心编程

  • 算法

你可能感兴趣的:(java,开发语言)