### 簡介
> java中,抽象類和接口是支持抽象概念的兩種機制,因為它們的存在,賦予了java強大的面向對象編程能 力。接口抽象類在抽象定義上有很多相似地方,甚至可以相互替換。但它們還是有區別的,下面從接口,抽象類以及兩者的區別等方面來分析。
### 一、抽象類
**在面向對象領域,一切都可以理解為對象,對象可以用類來描述。但不是所有的類都是來描述對象的。這些類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。**
抽象類往往用來表征我們在對問題領域進行分析、 設計中得出的抽象概念,是對一些類的本質的抽象。比如在車子的類別中,有自行車,橋車,它們的本質屬性都可以歸類為車,但這個車不能描述出自行車和橋車的區別,需要通過自行車的定義來具體描述車的性質,所以車可以理解為一個抽象類的概念。
(1).在面向對象中,抽象類是不能是實例化的,在抽象類中可以定義一組抽象方法,即沒有具體實現的方法,在方法前加上abstract關鍵字來修飾。這些抽象方法的實現需要具體的派生類去實現。
(2)抽象類也可以繼承,其目的也是為了體現繼承,抽取出類的相同性質,體現OOP原則。所以在使用抽象類時需要注意以下幾點:
1. 抽象類不能被實例化,若一個類包含了一個以上的抽象方法,那么這個類也必須定義為抽象類(即必須也用abstract來修飾這個類)。
2. 抽象類的抽象方法必須由其其子類實現。
3. 抽象類中可以保護具體的實現方法,也可以不包含抽象方法
4. abstract不能與final并列修飾同一個類。
5. abstract 不能與private、static、final或native并列修飾同一個方法。
下面通過一個實例來說明
~~~
public abstract class Bird {
public abstract void fly();
public void eat(){
System.out.println("鳥會吃蟲子...");
}
}
public class Eagle extends Bird {
@Override
public void fly() {
}
public void crash(){
System.out.println("Eagle...會抓老鼠");
}
}
public class Parrot extends Bird {
@Override
public void fly() {
}
public void sign(){
System.out.println("Parrot ");
}
}
public class AbtractTest {
public static void main(String[] args) {
Bird b1=new Parrot();
Bird b2=new Eagle();
b1.fly();
b2.fly();
}
}
~~~
### 二、接口
接口不是類,是類的功能的描述,不能實例化一個接口,只能new接口的實現類。它比抽象類更加抽象。接口是類所依賴的一種規范化形式,沒有具體的實現方法,若實現該接口類,則必須實現該接口的所有方法,用implements是實現,接口的定義由interface聲明。
接口是對抽象類的一種可擴展,因為抽象類是不能實現多繼承的,但接口可以實現多繼承,各被繼承的接口由逗號分隔,當然接口和抽象類可以聯合使用,如 A extends B implements C,D{};
在接口使用中需要注意以下幾點:
1.接口中的所有方法必須要被實現。
2.接口只可以定義不可變的成員變量。如 static final String A_PARAM=”“;
3.接口不能用new去實例化,但可以聲明一個接口變量,該變量必須引用一個實現該接口的類的對象,可以使用 instanceof 檢查一個對象是否實現了某個特定的接口。例如:if(anObject instanceof Comparable){}。
實例介紹如下:
~~~
#接口
public interface Common {
public void run() throws Exception;
}
#實現類
public class CommonImpl implements Common {
@Override
public void run() throws Exception {
}
}
public class InterfaceTest {
public static void main(String[] args) throws Exception {
CommonImpl cl=new CommonImpl();
cl.run();
}
}
~~~
### 三、接口和抽象類的區別
盡管接口和和抽象類有很多相似處,都是用來被繼承或被實現,但也有區別,下面從方式的實現,構造器,訪問修飾符,多繼承,效率等方面進行比較:
| 參數 | 抽象類 | 接口 |
|-----|-----|-----|
| 默認的方法實現 | 它可以有默認的方法實現 | 接口完全是抽象的,它根本不存在方法的實現 |
| 實現 | 子類使用extends關鍵字來繼承抽象類。如果子類不是抽象類的話,它需要提供抽象類中所有聲明的方法的實現。 | 子類使用關鍵字implements來實現接口。它需要提供接口中所有聲明的方法的實現 |
| 構造器 | 抽象類可以有構造器 | 接口不能有構造器 |
| 修飾符 | 抽象方法可以有public、protected和default這些修飾符 | 接口方法默認修飾符是public。你不可以使用其它修飾符。 |
| main方法 | 抽象方法可以有main方法并且我們可以運行它 | 接口沒有main方法,因此我們不能運行它。 |
| 多繼承 | 抽象方法可以繼承一個類和實現多個接口 | 接口只可以繼承一個或多個其它接口 |
| 效率 | 它比接口速度要快 | 接口是稍微有點慢的,因為它需要時間去尋找在類中實現的方法。 |
| 添加新方法 | 如果你往抽象類中添加新的方法,你可以給它提供默認的實現。因此你不需要改變你現在的代碼。 | 如果你往接口中添加方法,那么你必須改變實現該接口的類。 |
### 四、總結
1.如果你擁有一些方法并且想讓它們中的一些有默認實現,那么使用抽象類吧。
2.如果你想實現多重繼承,那么你必須使用接口。由于Java不支持多繼承,子類不能夠繼承多個類,但可以實現多個接口。因此你就可以使用接口來解決它。
3.如果基本功能在不斷改變,那么就需要使用抽象類。如果不斷改變基本功能并且使用接口,那么就需要改變所有實現了該接口的類。