抽象類和介面,你瞭解多少?

北漂程式設計師發表於2022-05-22

  現在的java開發一般都說面向介面程式設計,在開發過程中使用的最多的是給service層每個方法寫一個介面,如果用到了DAO層,那麼也是一個Mapper介面,之後的事情就交給mybatis框架去做了。總之程式設計過程中充斥著介面,有一個和介面很相似的叫做“抽象類”的不知道是否還記得。今天想聊聊介面和抽象類的那些事。

一、什麼是介面,什麼是抽象類

  介面和抽象類就像是一隊孿生兄弟,有時候除了從定義上來區分,其他地方用什麼似乎都是可以的。

  介面,可以理解為定義一組協議,一類操作流程。經常聽到“你把這個類抽象出一個介面出來”這樣的話,那麼介面是什麼樣子,如在java的API中有AutoCloseable介面,

該介面僅僅定義了一個close()方法,丟擲Exception異常,看下該介面上的註釋

意思大概是close()方法不像java.io.Closeable介面中的close()方法需要冪等性,該介面不需要冪等性,同時強烈建議實現類或介面實現自己的close()方法。既然提到了java.io.Closeable那麼我們看下該介面是什麼樣子的,

該介面繼承了java.lang.AutoCloseale介面,且有自己的close()方法,該方法丟擲的是IOException,也就是說該介面和IO相關。

從上面我們可以得出一個結論介面是可以繼承介面的

我們比較java.lang.AutoCloseable和java.io.Closeable這兩個介面,都是隻有兩個close()方法,但看java.lang.AutoCloseable介面,你根本看不出什麼東西,它可以說是一個高度的抽象,僅僅是關閉一個資源,而且丟擲的是Exception異常,簡直太抽象了,感興趣的可以閱讀下該類上的註釋。那麼到了java.io.Closeable同樣是一個close()方法,不過這裡確實丟擲一個IOExcetion異常,那麼就是和IO相關的拉。從上面可以看出介面肯定是高度抽象的。反觀我們平時寫的程式碼,動不動就是一個介面,抽象程度肯定不夠,

下面看下java.io.Closeable的一個實現類java.io.InputStream,你沒看錯就是平時使用的檔案操作類InputStream,它不是一個介面,而是一個抽象類

從上圖可以看到InputStream實現了Closeable介面,且該抽象類中還有其他一些read()、skip()、avaliable()方法等。

先看下實現的close()方法吧,

該方法是一個空方法,沒用任何實現,意味著等待InputStream的子類去覆蓋,例如BufferedInputStream是這樣實現的,

再回過頭來看下InputStream類中的read()方法,

這個方法是抽象的,而另外一個read()方法是有實現的,

從這裡可以看出,抽象類中可以有非抽象方法

 

  舉了這麼多的例子,無非是想大家對介面和抽象類能有一個感官上的認識,現在對其做個總結,

  介面定義了一組協議或標識某個功能,介面可以實現介面,介面中的方法都是public static final的。

  抽象類是一種特殊的類,無法例項化,只能被繼承,只要類中有一個方法是抽象的那麼該類就說抽象的,抽象類中可以有非抽象方法。

  java8開始介面中可以有default修飾的方法。

二、怎麼使用介面,怎麼使用抽象類

前面說了很多關於介面和抽象類的內容,那麼介面和抽象類要怎麼使用,想必定義都是不陌生的,類似,

package com.my.day01;

/**
 * 汽車介面
 * @date 2022/5/22 21:00
 */
public interface CarInterface {
    void run()throws Exception;
}

抽象類,

package com.my.day01;

/**
 * 抽象的汽車類
 * @date 2022/5/22 21:02
 */
public abstract class AbstractCar implements CarInterface {
    @Override public void run() throws Exception {
        System.out.println("running.....");
    }
    /**
     * 加油
     * 不同的car加的油不一樣,有汽油、柴油,有92 95等
     */
    public abstract void fillGas();
    /**
     * 掛擋
     */
    public void gear() {
        System.out.println("掛擋");
    }
}

上面就是介面和抽象類的使用,有個很重要的問題,什麼時候該用介面什麼使用該用抽象類,我有這樣的一些想法,供參考。介面必須是高度抽象的,從所有的類中抽象出來公有的方法,那麼這個方法就應該是在介面中;對於一些不是所有的類都有的行為,我們可以抽取到抽象類中實現為抽象方法,供不同的子類去實現。我認為介面和抽象類之間還是有不少區別的。

三、介面、抽象類的區別是什麼

  介面和抽象類中有什麼樣的區別?難到不可以僅用其中一個嗎?這個肯定是不行的。首先,介面定義的是一組規範,一組協議,她不負責任何實現,而在抽象類中是可以有非抽象方法的,也就是說抽象類可以提供一部分實現,僅把部分作為抽象供子類去覆蓋;其次,現在都講面向介面程式設計,你給人提供API的時候給一個抽象類那豈不是把你的實現也告訴別人了嗎。

四、總結

  本文主要是由介面和抽象類這個基礎點,帶來的一些思考,越是常見的知識越容易被忽略。又不正之處歡迎指正。

 

相關文章