繼承是 Java 面向對象程式設計(OOP)的基石之一,它允許開發者建立具有層級關係的類別體系。簡單來說,繼承讓子類別能夠取得父類別的特徵(屬性)與行為(方法),使子類別實例擁有父類別的實例變數與方法,或透過繼承方法讓子類別具備相同的行為模式。

以動物分類為例:兔子和羊屬於草食動物,獅子和豹屬於肉食動物;草食動物和肉食動物同屬動物界。這完美詮釋了繼承必須符合的 is-a(是一種) 關係——父類別更通用,子類別更具體。雖然草食動物和肉食動物都是動物,但兩者在屬性與行為上存在差異,因此子類別既保有父類別的通用特性,又擁有自身獨特的特徵。
在 Java 中,透過 extends 關鍵字宣告一個類別繼承自另一個類別,基本語法如下:
class 父類別 { }
class 子類別 extends 父類別 { }
假設我們要開發動物類別,包含企鵝與老鼠,兩者都擁有姓名、ID 以及吃、睡、自我介紹等方法。若分別編寫兩個類別,程式碼將高度重複:
public class Penguin {
private String name;
private int id;
public Penguin(String myName, int myid) { name = myName; id = myid; }
public void eat(){ System.out.println(name + "正在吃"); }
public void sleep(){ System.out.println(name + "正在睡"); }
public void introduction() { System.out.println("大家好!我是" + id + "號" + name + "."); }
}
public class Mouse {
private String name;
private int id;
public Mouse(String myName, int myid) { name = myName; id = myid; }
public void eat(){ System.out.println(name + "正在吃"); }
public void sleep(){ System.out.println(name + "正在睡"); }
public void introduction() { System.out.println("大家好!我是" + id + "號" + name + "."); }
}
這種寫法導致程式碼臃腫、維護困難(修改時需同步更新多處,易出錯)。解決之道是將共同部分提取為父類別:
public class Animal {
private String name;
private int id;
public Animal(String myName, int myid) { name = myName; id = myid; }
public void eat(){ System.out.println(name + "正在吃"); }
public void sleep(){ System.out.println(name + "正在睡"); }
public void introduction() { System.out.println("大家好!我是" + id + "號" + name + "."); }
}
public class Penguin extends Animal {
public Penguin(String myName, int myid) { super(myName, myid); }
}
public class Mouse extends Animal {
public Mouse(String myName, int myid) { super(myName, myid); }
}
透過繼承,子類別自動擁有父類別的屬性與方法,消除了重複程式碼,大幅提升維護性與複用性。
private 的屬性與方法。實現類別繼承,語法上子類別只能 extends 一個父類別:
public class Animal { /* ... */ }
public class Penguin extends Animal { }
用於類別實作介面,讓 Java 具備「多實作」特性,可同時實作多個介面(以逗號分隔):
public interface A { void eat(); void sleep(); }
public interface B { void show(); }
public class C implements A, B { }
super:引用當前物件的父類別,用於存取父類別被隱藏的成員(屬性/方法/建構子)。this:引用當前物件本身。範例:
class SuperClass { int i = 50; }
class SubClass extends SuperClass {
int i = 100;
public void showMessage() {
System.out.printf("super.i = %d, this.i = %d\n", super.i, this.i);
}
}
// 輸出:super.i = 50, this.i = 100
final class 類別名 { } —— 該類別無法被繼承(最終類別)。註:被宣告為 final 的類別,其方法自動成為 final,但實例變數不自動成為 final。
子類別 不會繼承 父類別的建構子。但子類別建構子中必須透過 super(參數列表) 顯式呼叫父類別帶參數的建構子。若父類別有無參數建構子,子類別未顯式呼叫 super() 時,系統會自動插入 super() 呼叫無參建構子。
class SuperClass {
private int n;
SuperClass(){ System.out.println("SuperClass()"); }
SuperClass(int n) { System.out.println("SuperClass(int n)"); this.n = n; }
}
class SubClass extends SuperClass {
private int n;
SubClass(){ super(300); System.out.println("SubClass()"); }
SubClass(int n){ System.out.println("SubClass(int n):" + n); this.n = n; }
}
public class TestSuperSub {
public static void main(String args[]){
// new SubClass(); // 輸出:SuperClass(int n) -> SubClass()
new SubClass(200); // 輸出:SuperClass() -> SubClass(int n):200
}
}
輸出結果:
SuperClass() SubClass(int n):200
解析:SubClass(200) 未顯式呼叫 super(...),故自動呼叫父類別無參建構子 SuperClass()。