電腦程式的思維邏輯 (20) - 為什麼要有抽象類別?【轉】

來源:互聯網
上載者:User

標籤:技術分享   ++   tle   []   方法   邏輯   自己實現   具體類   targe   

基本概念

上節提到了一個概念,抽象類別,抽象類別是什麼呢?顧名思義,抽象類別就是抽象的類,抽象是相對於具體而言的,一般而言,具體類有直接對應的對象,而抽象類別沒有,它表達的是抽象概念,一般是具體類的比較上層的父類。

比如說,狗是具體對象,而動物則是抽象概念,櫻桃是具體對象,而水果則是抽象概念,正方形是具體對象,而圖形則是抽象概念。下面我們通過一些例子來說明Java中的抽象類別。

抽象方法和抽象類別

之前我們介紹過圖形類Shape,它有一個方法draw(),Shape其實是一個抽象概念,它的draw方法其實並不知道如何?,只有子類才知道。這種只有子類才知道如何?的方法,一般被定義為抽象方法。

抽象方法是相對於具體方法而言的,具體方法有實現代碼,而抽象方法只有聲明,沒有實現,上節介紹的介面中的方法就都是抽象方法。

抽象方法和抽象類別都使用abstract這個關鍵字來聲明,文法如下所示:

public abstract class Shape {    // ... 其他代碼    public abstract void draw();}

定義了抽象方法的類必須被聲明為抽象類別,不過,抽象類別可以沒有抽象方法。抽象類別和具體類一樣,可以定義具體方法、執行個體變數等,它和具體類的核心區別是,抽象類別不能建立對象(比如,不能使用new Shape()),而具體類可以。

抽象類別不能建立對象,要建立對象,必須使用它的具體子類。一個類在繼承抽象類別後,必須實現抽象類別中定義的所有抽象方法,除非它自己也聲明為抽象類別。圓類的實現代碼,如下所示:

public class Circle extends Shape {    //...其他代碼        @Override    public void draw() {        // ....    }}

圓實現了draw()方法。與介面類似,抽象類別雖然不能使用new,但可以聲明抽象類別的變數,引用抽象類別具體子類的對象,如下所示:

Shape shape = new Circle();shape.draw();

shape是抽象類別Shape類型的變數,引用了具體子類Circle的對象,調用draw方法將調用Circle的draw代碼。

為什麼需要抽象類別?

抽象方法和抽象類別看上去是多餘的,對於抽象方法,不知道如何?,定義一個空方法體不就行了嗎,而抽象類別不讓建立對象,看上去只是增加了一個不必要的限制。

引入抽象方法和抽象類別,是Java提供的一種文法工具,對於一些類和方法,引導使用者正確使用它們,減少被誤用。

使用抽象方法,而非空方法體,子類就知道他必須要實現該方法,而不可能忽略。

使用抽象類別,類的使用者建立對象的時候,就知道他必須要使用某個具體子類,而不可能誤用不完整的父類。

無論是寫程式,還是平時做任何別的事情的時候,每個人都可能會犯錯,減少錯誤不能只依賴人的優秀素質,還需要一些機制,使得一個普通人都容易把事情做對,而難以把事情做錯。抽象類別就是Java提供的這樣一種機制。

抽象類別和介面

抽象類別和介面有類似之處,都不能用於建立對象,介面中的方法其實都是抽象方法。如果抽象類別中只定義了抽象方法,那抽象類別和介面就更像了。但抽象類別和介面根本上是不同的,一個類可以實現多個介面,但只能繼承一個類。

抽象類別和介面是配合而非替代關係,它們經常一起使用,介面聲明能力,抽象類別提供預設實現,實現全部或部分方法,一個介面經常有一個對應的抽象類別。

比如說,在Java類庫中,有:

  • Collection介面和對應的AbstractCollection抽象類別
  • List介面和對應的AbstractList抽象類別
  • Map介面和對應的AbstractMap抽象類別

對於需要實現介面的具體類而言,有兩個選擇,一個是實現介面,自己實現全部方法,另一個則是繼承抽象類別,然後根據需要重寫方法。

繼承的好處是複用代碼,只重寫需要的即可,需要寫的代碼比較少,容易實現。不過,如果這個具體類已經有父類了,那就只能選擇實現介面了。

我們以一個例子來進一步說明這種配合關係,還是用前面兩節中關於add的例子,上節引入了IAdd介面,代碼如下:

public interface IAdd {    void add(int number);    void addAll(int[] numbers);}

我們實現一個抽象類別AbstractAdder,代碼如下:

public abstract class AbstractAdder implements IAdd {    @Override    public void addAll(int[] numbers) {        for(int num : numbers){            add(num);        }    }}

這個抽象類別提供了addAll方法的實現,它通過調用add方法來實現,而add方法是一個抽象方法。

這樣,對於需要實現IAdd介面的類來說,它可以選擇直接實現IAdd介面,或者從AbstractAdder類繼承,如果繼承,只需要實現add方法就可以了。這裡,我們讓原有的Base類繼承AbstractAdder,代碼如下所示:

public class Base extends AbstractAdder {    private static final int MAX_NUM = 1000;    private int[] arr = new int[MAX_NUM];    private int count;        @Override    public void add(int number){        if(count<MAX_NUM){            arr[count++] = number;            }    }}

小結

本節,我們談了抽象類別,相對於具體類,它用於表達抽象概念,雖然從文法上,抽象類別不是必須的,但它能使程式更為清晰,減少誤用,抽象類別和介面經常相互配合,介面定義能力,而抽象類別提供預設實現,方便子類實現介面。

在目前關於類的描述中,每個類都是獨立的,都對應一個Java原始碼檔案,但在Java中,一個類還可以放在另一個類的內部,稱之為內部類,為什麼要將一個類放到別的類內部呢?

----------------

電腦程式的思維邏輯 (20) - 為什麼要有抽象類別?【轉】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.