我如何理解Java中抽象類和介面
在面試中我們經常被問到:Java中抽象類和介面的區別是什麼?
然後,我們就大說一通抽象類可以有方法,介面不能有實際的方法啦;一個類只能繼承一個抽象類,卻可以繼承多個介面啦,balabala一大堆,就好像把標準答案熟練的說出來一樣。
抽象類和介面這篇文章講到了他們的區別和聯絡,它們確實有很多相似的地方,但是從本質上看,或從語言的設計角度來看,這不是它們最本質的區別。
不賣關子,我個人對這兩個的理解:
類是具體例項的抽象,比如一個json字串的抽象;而抽象類就是類的抽象;介面就是抽象類的抽象,介面更像是一種協議
聽我慢慢道來~
吐槽
首先,我必須吐槽一下這種面試,我認為面試官凡事問出這種類似“說說抽象類和介面的區別”,“說說程式和執行緒的區別”等等問題,都是不負責的表現。
為什麼呢?
一個原因就是,面試官對想要招的人完全沒有自己的評價標準,另一個原因就是對面試者不負責。這種問題根本不能考驗面試者的水平。
那麼,如果我來面試別人,我會問:請你說說你怎麼理解抽象類和介面;如果要你向你外婆解釋程式和執行緒的區別,你會怎麼解釋?
我覺得這可以考驗面試者對問題的理解程度,我想微軟的面試題(你如何向你奶奶解釋Excel)一樣,考驗一個人對某一事物的理解程度(雖然,至今我還不能很好的想明白這個問題 -。-)
抽象類和介面的區別
說到抽象類和介面,就必須要說到類。
一個類就是對現實事物的抽象。
比如定義一個BenzCar類,就需要對現實的賓士汽車有很好的抽象(當然賓士汽車有好多系列,這裡不鑽牛角尖)。也就是說如果你要造一輛賓士汽車,就需要BenzCar這個類(這輛賓士汽車就是記憶體中的一個Instance)。
那麼抽象類就是對類的抽象。
怎麼理解呢?就是說有很多汽車廠商一起定義一種規範(Car類),說要造一輛汽車就需要有發動機,輪胎,音響裝置…(這些就相當於抽象方法),具體用什麼發動機,輪胎,音響裝置由每個汽車廠商自己去完成。這樣就有各種汽車了,賓士牌的,寶馬牌的,豐田牌的…
介面就是對抽象類的抽象
這只是我個人的理解。
在我們日常生活中可以看到各種“介面”,電源插座就是一種。開始我是看到耗子叔的部落格在開始理解“控制翻轉”這個概念的——IoC/DIP其實是一種管理思想| 酷殼- CoolShell.cn。後來我就想,這個東西其實無處不在,製造電源插座的廠和製造電器的廠只要約定一種“介面”——兩口插座或三口插座,當然每個國家的介面都不一樣,不同介面之間的轉換就需要用介面卡了。
其實程式中也一樣,比如所有的交通工具可以抽象為一個介面Drivable(可能由於經驗原因,我考慮的不是很完善),表示實現這個介面的類建立的物件(比如:汽車,飛機,輪船等等)都是可以駕駛的
public interface Drivable{ public void drive(); }
然後,我們就可以建立一個AbstractCar類,表示這個對所有汽車類的一個抽象,所有可以駕駛的汽車都必須繼承這個類,這個抽象類中規定了一些抽象方法,比如getEngine()方法,這說明每種汽車的引擎都不太一樣,需要在子類中自定義(當然,你也可以繼承AbstractCar類,對所有可能具有相同引擎的汽車進行一層抽象)。
為什麼對Drivable的drive()方法進行了預設實現,但是預設實現中卻直接丟擲了異常呢?
其實這是一種實現介面的方法,還有一種方法就是將drive()設為abstract。這兩種實現方式,我覺得從功能上講是一樣的,但是從類設計上講是不同的。
下面程式碼中的實現,我是參考了java.util.AbstractList<E>中add(int location, E object)方法的設計,它的文件中寫到:
* @throws UnsupportedOperationException * if adding to this List is not supported.
public abstract class AbstractCar implements Drivable { public abstract Engine getEngine(); public abstract Wheel getWheel(); @Override public void drive(){ throw new UnsupportedOperationException(); } // 省略其他方法和屬性 }
那麼上面這段程式碼中的drive()可以理解為:
預設情況下“汽車”是不能開的,你實現了一個汽車類後,需要Override這個方法,實現自己的drive方法
以java容器中的List舉例
到原始碼裡面找,你就會發現List<E>的繼承關係最頂層的就是Iterable,就表示說List是可以遍歷的,而且它還會產生一個Iterator介面物件。這表示一個列表可以通過這個迭代器來遍歷。
這就像上面說的,所有的交通工具都是可以駕駛的一樣,所有的列表都是可以遍歷的。
一層一層往下,類就變得更加具體。
最後
為什麼介面可以繼承?
其實這個原理很簡單。因為總有一個最本質的協議來約束大家,比如所有的交通工具都是可以駕駛的,所有的容易都是可以遍歷的。然後協議會漸漸變得更加具體:
Iterable <- Collection <- List <- AbstractList <- List
從下往上看,就是一層比一層抽象。
就像我在文章開頭說的,
- 你用ArrayList類可以建立很多個物件,ArrayList就是這些物件的一次抽象
- 而AbstractList是對ArratList的一次抽象,你用AbstractList可以建立ArrayList,也可以建立Stack,或LinkedList等
- List介面就是對所有的列表類的抽象
- Collection就是對所有單一元素的容器的抽象
- Iterable就是一個最高層次的抽象了,表示所有的容器都是可以遍歷的
注:
應該有很多我考慮不周全的地方,歡迎大家指正並且討論
相關文章
- 我是如何理解Java抽象類和介面的Java抽象
- java中抽象類和介面Java抽象
- java介面和抽象類的簡單理解Java抽象
- 深入理解Java的介面和抽象類Java抽象
- 結合實戰理解 Java 抽象類和介面Java抽象
- Java的抽象類與介面理解Java抽象
- Java中抽象類和介面的區別Java抽象
- 深入理解java的抽象類和介面(轉載)Java抽象
- java中的抽象類與介面Java抽象
- Java抽象(方法,類)和Java的介面Java抽象
- Java基礎-抽象類和介面Java抽象
- Java抽象類和介面 小白版Java抽象
- 關於抽象類和介面的初步理解抽象
- 介面和抽象理解抽象
- 介面和抽象類抽象
- 抽象類和介面抽象
- 架構師帶你深入理解Java的介面和抽象類架構Java抽象
- Java的抽象類 & 介面Java抽象
- Java中抽象類與介面的區別Java抽象
- java中抽象類跟介面的區別Java抽象
- Java中的介面與抽象類詳解Java抽象
- JAVA中介面和抽象類的區別Java抽象
- JAVA基礎之三-介面和抽象類Java抽象
- 介面和抽象類 (abstract)抽象
- java抽象類和抽象方法Java抽象
- Java學習筆記之介面和抽象類Java筆記抽象
- Java 8 中的抽象類和介面到底有啥區別?Java抽象
- MVP模式(2):你真的理解下抽象類和介面嗎??MVP模式抽象
- 介面和抽象類詳解抽象
- PHP中的 抽象類(abstract class)和 介面(interface)PHP抽象
- PHP 中的抽象類(abstract class)和介面(interface)PHP抽象
- java-介面和抽象類的聯絡和區別。Java抽象
- Java總結-抽象類與介面Java抽象
- JAVA介面繼承、抽象類等Java繼承抽象
- Java中的介面與抽象類設計原則Java抽象
- Java 的抽象類, 介面以及內部類Java抽象
- Java 基礎鞏固:再談抽象類和介面Java抽象
- 介面的行為抽象和抽象類的行為抽象抽象