設計模式(04):接口和抽象類

接口和抽象類

區別

接口是對行爲的抽象,其重點關注的是要有該行爲。


抽象類是對一些共性行爲的聚合,將多個子類都有的具體行爲抽象成一個方法,形成複用。

public abstract class Bird {
    private String name;
    private BigDecimal weight;
    private String habit;
}

public interface IFlyable {
    /**
     * a bird that can fly
     */
    void fly();
}

public class Sparrow extends Bird implements IFlyable {
    @Override
    public void fly() {
        Console.log("Sparrow can fly");
    }
}

舉例來說,這裏我們首先定義了一個 Bird 類,但是,我們卻無法在其中定義 fly 方法,爲什麼呢?


因爲並不是所有鳥都會飛的,如果是在 Bird 中定義的話,那麼所有實現子類,都擁有這個行爲,因此,我們考慮定義接口,來將其行爲抽象成一種能力,只要有該能力的類都可以實現該類,這這裏,你甚至可以定義飛機來實現 IFlyable。


而從語法特性來描述的話,有如下區別:

  • 接口不能有屬性,而抽象類可以有屬性和方法;
  • 接口中方法不能被實現(Java8 後可以有默認實現方法),抽象類中的方法可以有實現,也可以沒有;

使用時機

從上面的例子中,也可以看出何時使用抽象類,何時使用接口,關鍵點是行爲的是否可繼承性。


此外,在 Java 要實現多繼承的時候,也只能使用接口,因爲 Java 不支持多繼承。

存在意義

首先說抽象類。抽象類本質也是一個類,因此類的繼承特性最首要的就是解決代碼複用的問題。


通過繼承,可以直接複用父類中的方法,並把需要子類來自定義實現的方法定義成 抽象方法,從而實現複用。


並且因爲繼承的關係,還可以使用面向對象中的 **多態 **特性,用抽象類的指針指向子類的對象。


如果說抽象類關注的是代碼複用的話,接口更加關注的就是 解耦。通過接口定義來讓第三方不要關注具體的實現,如果你要調用或是實現自己的方法的話,關注定義即可。


深入瞭解

通過,對接口和抽象類的瞭解,現在,我們來看一下,如何在不支持上述語法特性的語言中,實現接口和抽象類呢。

在這裏,因爲沒有裝 py 和 C++ 的環境,因此就用 Java 簡單代替一下,所完成的邏輯和方法是 的。


用抽象類來實現接口的定義:

/**
 * @author iceWang
 * @date 2020/10/17
 * 用抽象類來模擬接口
 */
public abstract class AbstractToInterface {
    protected AbstractToInterface(){};

    /**
     * 類似於接口中的定義,子類必須要實現
     */
    public abstract void demo();
}


用普通類來實現抽象類的作用:

/**
 * @author iceWang
 * @date 2020/10/17
 * 用普通類來模擬抽象類
 */
public class ClassToAbstractClass {
    protected ClassToAbstractClass() {
    }

    /**
     * 類似於抽象類中的抽象方法的定義,因爲要保證子類必須重寫,因此直接拋出異常
     */
    public void abstractFunction() throws Exception {
        throw new Exception("Error DesignModel");
    }

    /**
     * 類似於抽象類中的普通方法的定義,子類不必一定重寫
     */
    public void plainFunction() {
        System.out.println("Hello DesignModel");
    }
}


用普通類來實現接口的定義:

/**
 * @author iceWang
 * @date 2020/10/17
 * 用普通類來模擬接口
 */
public class ClassToInterface {
    protected ClassToInterface() {
    }

    /**
     * 類似於接口中的定義,因爲要保證子類必須實現,因此直接拋出異常
     */
    public void demo() throws Exception {
        throw new Exception("111");
    }
}

接口的使用

接口的實現,可以讓我們在編程時採用 面向接口編程 的思想,即只關注接口定義即可,不必過多關注具體的實現細節,從而實現兩方的解耦。


而爲了支持面向接口編程,需要在開發過程中:

  • 函數的命名不能暴露任何實現細節;
  • 具體的實現細節進行封裝,不暴露給調用者;

公衆號截圖




文章在公衆號「iceWang」第一手更新,有興趣的朋友可以關注公衆號,第一時間看到筆者分享的各項知識點,謝謝!筆芯!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章