許多人初學 Java 時,或許難以理解 抽象類別 和 介面 的差異,
簡單整理摘要如下,若有誤還望各位先進指點 Orz
概述
抽象類別 (Abstract Class)
- 使用
abstract
定義抽象類別 (不得宣告為final class
) - 無法實體化的類別 (即無法透過
new
關鍵字產生實體)
或許會看到如下這種程式碼- AbstractFooClz.java
1
2
3public abstract AbstractFooClz {
protected abstract void doBar();
} - TestMain.java這是屬於匿名類別,終究不是原本的抽象類別,因此要特別注意!(小弟曾認為這也是
1
2
3
4
5
6
7
8
9
10public class TestMain {
public static void main(String[] args) {
new AbstractFooClz() {
protected void doFoo() {
System.out.println("do foo here.");
}
}.doFoo();
}
}new AbstractFooClz
的一種…)
- AbstractFooClz.java
- 專門被拿來當作父類別的類別,具有範本作用
- 只能被繼承 (使用
extends
關鍵字),子類別需實作抽象方法 (否則繼續抽象下去) - 其__抽象方法 (abstract method)__封裝等級不能是
private
(即必須是public/protected/(default)
)
abstract 回傳值型別 抽象方法名稱(參數列);
// 沒有方法實體,以 ; 做結尾 - 包含抽象方法的類別,一定要宣告為抽象類別;但是抽象類別不一定有抽象方法
介面 (Interface)
- 定義屬性成員皆為常數 (即預設
public static final
),因此必須給定初始值 - 定義方法時,只能為抽象方法 (即預設
public abstract
,定義功能的名稱,實作部分留給相關類別 override- IBar.javaJava8 開始多了
1
2
3
4public interface IBar {
int MY_NUMBER = 0; // 編譯器視為 public static final int MY_NUMBER = 0;
void doBar(); // 編譯器視為 public abstract void doBaz();
}default
關鍵字,可替介面加上預設實作,範例如下
(小弟目前還沒有 Java8 開發經驗,還望各位先進指點實務上如此設計之意義) - IBaz.java
1
2
3
4
5public interface IBaz {
default doBaz() {
System.out.println("only Java8 can do default baz here.");
}
}
- IBar.java
- 不一定需要定義方法,即空介面 (ex:
java.io.Serializable
) - 只能被實作 (使用
implements
關鍵字),子類別需實作抽象方法 (否則需宣告為抽象類別) - 子類別實作抽象方法修飾字必須是
public
(抽象方法預設使用public
修飾)
比較
相同點
- 兩者都無法直接實體化
- 子類別都必須實作已宣告之抽象方法 (或繼續抽象)
相異點
抽象類別 Abstract Class | 介面 Interface | |
---|---|---|
父類別/父介面 繼承 | 只能繼承一個類別 | 能繼承多個介面 (Java實現多重繼承) |
子類別 繼承/實作 | 只能繼承 (extends ) 一個抽象類別 |
能實作 (implements ) 多個介面 |
方法 | 可包含非抽象方法 | 只能是抽象方法 (Java8以前…XD) |
應用 | 關係密切的類別中 如定義抽象類別 Car 子類別 Benz 及 Audi 繼承 Car |
定義一些功能給較不相干類別使用 如定義介面飛翔 Fly 子類別 AirPlane 及 Bird 實作 Fly 但實務上其實不會不相干類別實作同一介面 |
必定為父類別 | 可視為抽象類別的特例 |