在前面 Modifiers 的介紹中,曾有提到抽象類別 abstract,但因為那時候還沒有提到繼承的概念,所以沒有磨墨太多。今天就讓我們來聊聊 Abstract Class。
Java 中的 Abstract Class 是一種不能被實體化成物件 (Object) 的類別,是專門用來「被繼承」的類別
。
為何要這樣說呢? 我們回到先前水果的例子,現實生活中確實存在檸檬、西瓜與葡萄這樣的水果,但其實不存在一種叫做水果的水果,因為水果本身是一種分類的概念,代表一群特定植物的果實,所以並不具有實體,而是抽象的存在。
所以如果遇到父類別本身並沒有要被實體化的需求時,我們可以將父類別定義為抽象類別(Abstract Class),所以在前面的例子,應該要把 Fruits 類別改成抽象類別。
public abstract class Fruits {
//...
}
而雖然 Abstract Class 無法被實體化為物件,但還是可以作為資料型別(data type)使用,用於需要做多型的時候。
// Fruits 不可被實體化
Fruits fruits = new Fruits();
// java: models.Fruits is abstract; cannot be instantiated
// 但可以拿來作為子類別的資料型別使用
Fruits grape = new Grape();
那 Abstract Class 除了可以包含一般的屬性與方法之外,還擁有一種特殊的方法叫做 抽象方法 abstract method。
只具有方法原型而沒有主體的 method 稱為 abstract method,主體就是方法定義中 { } 與其中的內容,其他的部分就稱為方法的原型,範例說明如:
// 方法原型
abstract 修飾符 回傳型態 方法名稱 (參數); // 沒有 {}
因此如果我們要在剛剛的 Fruits 抽象類別範例中,新增一個抽象方法 eat(),可以這樣寫:
public abstract class Fruits {
// 定義抽象方法
abstract void eat();
}
而 Abstract method 只能存在於 Abstract Class 當中,如果有 class 繼承了該 Abstract Class,就必須實作或稱作覆寫(override)出來父類別所有的 Abstract method,以上面的例子來說,所有繼承 Fruits 的類別就都需要覆寫屬於自己的 eat() 方法。
// Watermelon 繼承抽象類別 Fruits
public class Watermelon extends Fruits {
// Watermelon 就必須實作/覆寫出 eat() 這個抽象方法
public void eat(){
System.out.println("eating watermelon...");
}
//...
}