工作好多年可能還未真正瞭解接口和抽象類

1. 抽象類和接口的定義和區別?

2. 抽象類在面向對象編程中解決了什麼問題?

3. 接口在面向對象編程中解決了什麼問題?

4. 如何決定該用抽象類還是接口?

5. 如果使用的語言不支持抽象類和接口,該如何應對?

 

抽象類

 

在面向對象編程的語言中,多數都添加了對抽象類和接口的支持,比如最常用的java,C#等語言。

//抽象類
    public abstract class Human
    {
        //抽象方法
        public abstract string Gender();
        //屬性
        public string Name { get; set; }
        //方法
        public int GetAge()
        {
            return 1;
        }
    }

以上是一個普通的抽象類的定義,具體怎樣使用,度娘有一大堆結果,其實總體來說抽象類主要有以下幾點特徵:

1. 抽象類不能被實例化,只能被繼承。也就是說如果 New Human()會報編譯錯誤

2. 抽象類也是類,可以包含屬性和方法,方法可以包含實現,也可以不包含,不包含實現被稱爲抽象方法。

3. 子類繼承抽象類,必須要實現定義的所有抽象方法,不然編譯器會報編譯錯誤。

 

抽象類本質上還是類,只不過是一種不能被實例化的特殊類而已,但是在面向對象的設計過程中卻起着非常重要的地位,本質上抽象類體現的是is-a的關係,就像上邊定義的抽象類一樣,Human類型抽象的是人類,假如我定義一個菜菜的類型來繼承這個類型 

 public class CaiCai : Human
    {
        public override string Gender()
        {
            return "男";
        }

    }

CaiCai這個類必須要提供抽象方法的實現纔可以通過編譯。抽象類的產生是面向對象開發思想的延伸,是解決代碼複用問題的一個方案,更是把代碼進行抽象化的一個結果。抽象類的設計思想是自下而上的,也就是說設計上應該先有子類,當子類逐漸增加,進而抽象出共用特性而產生抽象類。

 

說到這裏,好多同學會問,如果我不用抽象類做父類也可以啊。不錯,普通的類當然也可以代替抽象類的地位。但是有幾點就看起來比較奇怪了

1. 父類也可以進行實例化了,但是其中要抽象的方法看起來就比較怪了,因爲這些方法只有子類中才有明確的定義,比如 以上代碼中Human這個類如果修改爲普通類型,那方法Gender()該返回什麼內容呢?

2. 在編譯期間,如果子類沒有實現父類的方法是不會報錯的,這就加大了排查問題的難度,如果需要重寫的方法很多,之後排查問題會非常頭疼

3. 抽象出來的父類如果可以被實例化,這本質上違反了面向對象的思想,畢竟父類是一個抽象化的概念,被實例化之後代表着什麼比較令人困惑

 

接口

 

接口在系統設計中,最重要的作用就是解耦。你應該聽過不止一次的“面向接口編程”和依賴倒置等思想,這些也是面向對象設計思想的一種體現。接口本質上是抽象出來的對象的行爲,或者叫做契約。在面向接口開發中,調用者不關心接口的實現,而是依賴於接口的定義,接口定義的穩定性代表着一個系統的穩定性,如果一個系統對外的接口定義有問題,那這個系統多半是會死人的。

    public interface IHuman
    {
        //接口行爲定義
        void Walk();
    }

以上只是一個簡單接口的定義而已,接口的抽象小到可以是一個對象的行爲抽象,大到可以是一個服務的行爲抽象,更有可能是一個系統的行爲抽象,所以接口是一個很泛的概念,但是本質上還是反應的是面向對象設計理念。由於接口是行爲的定義,所以就決定了它有以下特點

1. 接口只能定義行爲,不能包含行爲的實現

2. 類型繼承接口的時候,必須要實現接口的所有行爲

3. 接口不同於類,不能包含屬性

 

由於接口體現的是行爲準則,所以接口在定義的時候也可以利用面向對象設計理念,當多個不同接口定義了相同的行爲,可以考慮抽象出更上層的接口來實現行爲的複用。

 

寫在最後

抽象類和接口都是對象的抽象行爲產生的,只不過抽象類更加側重於 is-a 的關係,它實現了代碼複用,而接口更加側重於行爲的抽象(has -a),舉一個很簡單的栗子,如果設計一個鳥類的抽象該怎麼做呢?不同的鳥可能羽毛的顏色不一樣,像這樣的屬性可以利用抽象類,不同的鳥類可能會有不同的飛行行爲,這樣行爲類的抽象利用接口來實現更加合適。

無論是接口還是抽象類,在代碼層次上體現的是上下級關係,就算一個編程語言沒有提供接口和抽象類的定義,只要能實現對象上下級關係,原理上也可以實現面向對象編程。編程的抽象思想始終在圍繞着上下,內外這幾個維度在合理的進化着。

說到接口的定義,其實還可以在泛化一下,接口中只有行爲方法的定義,在一些不支持接口的編程語言中,可以把只包含方法的類看做接口的抽象定義,這在設計理念上是說的通的。

在繼承層次上和設計流程上,抽象類是一種自下而上的設計思路,先有子類的代碼,當子類逐漸增多,纔會抽象出更加上層的父類。而接口不同,面向接口編程是一種自上而下的設計思路,先抽象出行爲契約,然後纔是實現。

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