最近,我接受了兩次電話採訪,有人問我接口和抽象類之間的區別。 我已經解釋了我能夠想到的各個方面,可是彷佛他們正在等我說起一些特定的內容,我不知道它是什麼。 php
根據個人經驗,我認爲如下是對的。 若是我缺乏要點,請告訴我。 html
接口: java
接口中聲明的每一個方法都必須在子類中實現。 接口中只能存在事件,委託,屬性(C#)和方法。 一個類能夠實現多個接口。 面試
抽象類: oracle
子類只須要實現Abstract方法。 Abstract類能夠具備實現的常規方法。 抽象類在事件,委託,屬性和方法旁邊也能夠具備類變量。 因爲C#中不存在多重繼承,一個類只能實現一個抽象類。 ide
畢竟,面試官提出了一個問題:「若是您有一個僅包含抽象方法的Abstract類,該怎麼辦?與接口有什麼不一樣?」 我不知道答案,但我認爲這是上面提到的繼承對嗎? 函數
另外一個面試官問我,若是接口內有一個Public變量,那和Abstract Class有什麼不一樣? 我堅持認爲,接口內不能有公共變量。 我不知道他想聽什麼,但他也不滿意。 工具
另請參閱 : ui
簡介:抽象類用於對外觀類似的類的類層次進行建模 (例如Animal能夠是抽象類,而Human,Lion,Tiger能夠是具體派生類)
和
接口用於2個類似/不類似類之間的通訊 ,這些類不關心實現接口的類的類型(例如,高度能夠是接口屬性,能夠由Human,Building,Tree來實現。是否能夠食用,您能夠游泳,能夠死去或其餘任何事情。.只重要於您須要具備Height的東西(在您的課堂中實施))。
儘管這個問題已經很老了,但我想補充一點,以支持接口:
可使用任何依賴關係注入工具來注入接口,其中不多有人支持Abstract類注入。
回答第二個問題: public
在定義的變量interface
是static final
默認,而public
在變量abstract
類是一個實例變量。
遺產
考慮一下汽車和公共汽車。 他們是兩種不一樣的車輛。 可是它們仍然具備一些共同的特性,例如具備轉向器,制動器,齒輪,發動機等。
所以,使用繼承概念,能夠將其表示爲...
public class Vehicle { private Driver driver; private Seat[] seatArray; //In java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections). //You can define as many properties as you want here ... }
如今是自行車...
public class Bicycle extends Vehicle { //You define properties which are unique to bicycles here ... private Pedal pedal; }
還有一輛車...
public class Car extends Vehicle { private Engine engine; private Door[] doors; }
這就是繼承 。 如上所述,咱們使用它們將對象分類爲更簡單的基本形式及其子對象。
抽象類
抽象類是不完整的對象。 爲了進一步理解它,讓咱們再次考慮車輛的類比。
能夠駕駛車輛。 對? 可是,不一樣的車輛以不一樣的方式行駛。例如,您不能像駕駛自行車同樣駕駛汽車。
那麼如何表現車輛的驅動功能呢? 很難檢查它是什麼類型的車輛並以其自身的功能駕駛它; 您必須在添加新型車輛時一次又一次地更改Driver類。
這裏是抽象類和方法的做用。 您能夠將drive方法定義爲抽象,以告訴每一個繼承的子代必須實現此功能。
所以,若是您修改車輛類別...
//......Code of Vehicle Class abstract public void drive(); //.....Code continues
自行車和汽車還必須指定如何駕駛。 不然,代碼將沒法編譯,並引起錯誤。
簡而言之,抽象類是具備某些不完整功能的部分不完整類,繼承子級必須指定它們本身的功能。
接口接口徹底不完整。 它們沒有任何屬性。 他們只是代表繼承的孩子有能力作某事...
假設您有不一樣類型的手機。 它們每一個都有不一樣的方式來執行不一樣的功能。 例如:打電話給一我的。 手機的製造商會指定如何進行。 手機能夠在此處撥打號碼-便可以撥打。 讓咱們將其表示爲接口。
public interface Dialable { public void dial(Number n); }
在這裏,「可撥號」的製造商定義瞭如何撥打號碼。 您只須要給它撥一個號碼便可。
// Makers define how exactly dialable work inside. Dialable PHONE1 = new Dialable() { public void dial(Number n) { //Do the phone1's own way to dial a number } } Dialable PHONE2 = new Dialable() { public void dial(Number n) { //Do the phone2's own way to dial a number } } //Suppose there is a function written by someone else, which expects a Dialable ...... public static void main(String[] args) { Dialable myDialable = SomeLibrary.PHONE1; SomeOtherLibrary.doSomethingUsingADialable(myDialable); } .....
所以,使用接口而不是抽象類,使用Dialable的函數的編寫者無需擔憂其屬性。 例如:它有觸摸屏或撥號盤嗎?是固定座機仍是移動電話。 您只須要知道它是否可撥號便可。 它是否繼承(或實現)了Dialable接口。
更重要的是 ,若是有一天您將Dialable切換爲其餘
...... public static void main(String[] args) { Dialable myDialable = SomeLibrary.PHONE2; // <-- changed from PHONE1 to PHONE2 SomeOtherLibrary.doSomethingUsingADialable(myDialable); } .....
您能夠確保代碼仍然能夠正常工做,由於使用可撥號功能的功能不(也不能)依賴於「可撥號」界面中指定的詳細信息。 它們都實現了Dialable接口,而這只是該函數所關心的。
開發人員一般使用接口來確保對象之間的互操做性(可互換使用),只要它們具備共同的功能(就像您可能須要更換座機或移動電話同樣,只要您撥打一個號碼便可)。 簡而言之,接口是抽象類的簡單得多的版本,沒有任何屬性。
另外,請注意,您能夠實現(繼承)任意數量的接口,但只能擴展(繼承)單個父類。
更多信息 抽象類與接口
After all that, the interviewer came up with the question "What if you had an Abstract class with only abstract methods? How would that be different from an interface?"
Docs清楚地指出,若是抽象類僅包含抽象方法聲明,則應將其聲明爲接口。
An another interviewer asked me what if you had a Public variable inside the interface, how would that be different than in Abstract Class?
默認狀況下,接口中的變量是public static和final。 若是抽象類中的全部變量都是公共的,該問題可能會被框起來? 好吧,它們仍然能夠是非靜態的和非最終的,與接口中的變量不一樣。
最後,我還要對上述提到的一點再加一點-抽象類仍然是類,而且屬於單個繼承樹,而接口能夠存在於多個繼承中。