正在載入...
請稍候
封面
示例歌曲名稱
示例藝術家
0:00 / 0:00

播放列表

第十二章:繼承

未分類
4.7k 字

什麼是「繼承」

繼承是 Java 的物件導向三大特性之一,讓子類別(Subclass)可以**重複使用父類別(Superclass)**的屬性和方法,避免重複撰寫程式碼。



類別繼承關係

名稱 說明 關鍵字 範例
父類別(超類別) 被繼承的類別 super class Animal {}
子類別(衍生類別) 繼承的類別 extends class Dog extends Animal {}



基本語法:使用 extends

1
2
3
4
5
6
7
8
9
10
11
12
class Animal {
String name;
void eat() {
System.out.println(name + " 正在吃飯");
}
}

class Dog extends Animal {
void bark() {
System.out.println(name + " 汪汪叫");
}
}
1
2
3
4
Dog d = new Dog();
d.name = "Bingo";
d.eat(); // 繼承來的
d.bark(); // 自己的



記憶體結構(Stack & Heap)

1
Dog d = new Dog();
區域 儲存什麼
Stack 變數 d(記憶體位置)
Heap Dog 物件(有 Dog 和繼承自 Animal 的欄位與方法)



方法覆寫(Override)

子類別可以改寫父類別的方法,稱為「覆寫」。

1
2
3
4
5
6
7
8
9
10
11
12
class Animal {
void eat() {
System.out.println("正在吃飯");
}
}

class Cat extends Animal {
@Override // 可寫可不寫
void eat() {
System.out.println("貓在吃魚");
}
}
1
2
Cat c = new Cat();
c.eat(); // 輸出:貓在吃魚
  • 加上 @Override 註解可讓編譯器檢查是否正確覆寫
  • 必須「方法名稱、參數、回傳型別」都一致!



super 關鍵字用法

super 表示「父類別(超類別)的參考」。

範例 1

用法 說明 範例
super.方法() 呼叫父類別的方法 super.eat()
super.屬性 存取父類別的變數 super.name
super(...) 呼叫父類別建構子 super("Bingo")
1
2
3
4
5
6
7
8
9
10
11
12
class Animal {
String name;
Animal(String name) {
this.name = name;
}
}

class Dog extends Animal {
Dog(String name) {
super(name); // 呼叫父類別的建構子
}
}

範例 2

用途 範例 解釋
呼叫父類別的建構子 super(); 通常放在子類別建構子的第一行
呼叫父類別的方法 super.printInfo(); 被子類別覆寫後仍可呼叫原方法
取得父類別的成員變數 super.name 當子類別與父類別變數重名時使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class Person {
String name = "Default";

public void printInfo() {
System.out.println("Person: " + name);
}
}

class Student extends Person {
String name = "Student";

public Student() {
super(); // 呼叫父類別的建構子
}

public void printInfo() {
super.printInfo(); // 呼叫父類別方法
System.out.println("Student: " + this.name); // this 是子類別自己
}
}

public class Main {
public static void main(String[] args) {
// ✅ 建立 Student 物件
Student s1 = new Student();
s1.printInfo();

System.out.println();

// ✅ 使用父類別參考指向子類別物件(多型)
Person p1 = new Student();
p1.printInfo(); // 只會呼叫覆寫後的方法(動態綁定)

System.out.println();

// ✅ 建立父類別物件
Person p2 = new Person();
p2.printInfo();
}
}



this vs super 對照表

比較項目 this(這個物件) super(父類別)
基本用途 指向目前類別建立的物件 指向目前類別的父類別所建立的物件
變數使用 訪問目前類別的屬性,常用於參數與成員變數重名時(this.name = name; 訪問父類別的屬性(如:super.name
方法使用 呼叫同一類別中其他方法(如:this.printInfo() 呼叫父類別的方法(如:super.printInfo()
建構子使用 呼叫同一類別中的其他建構子(如:this("Tom"); 呼叫父類別的建構子(如:super("Tom");
使用限制 只能用在方法或建構子中
this(...) 必須在建構子第一行
只能用在子類別中
super(...) 也必須在建構子第一行
是否能同時用 ✅ 可以在同一方法或建構子中使用(但 this()super() 不能同時存在建構子第一行) ✅ 可以在方法中混用,但建構子中兩者不能同時用
常見用途 區分參數與成員變數
內部方法呼叫
建構子間呼叫
使用父類別成員(屬性與方法)
呼叫父類別建構子
隱含對象 當前子類別的物件實體 子類別中的父類別物件實體



常見錯誤

  • this()super() 只能出現在建構子的第一行,不能同時存在。
  • 混淆了 this.namesuper.name:要看你是要指自己的變數還是繼承來的。

詳細說明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person {
String name = "PersonName";
}

class Student extends Person {
String name = "StudentName";

public void printNames() {
System.out.println("this.name: " + this.name); // 子類別的 name
System.out.println("super.name: " + super.name); // 父類別的 name
}
}

public class Main {
public static void main(String[] args) {
Student s = new Student();
s.printNames();
}
}



實作題範例

  • 父類別為 Person,有屬性 name,方法 printInfo()
  • 子類別為 Student,有自己的 name 屬性,覆寫 printInfo() 方法,並使用 super 呼叫父類別的 printInfo()
  • main() 方法中建立一個 Student 物件並呼叫 printInfo() 方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Person {
String name = "Default";

public void printInfo() {
System.out.println("Person: " + name);
}
}

class Student extends Person {
String name = "Student";

public void printInfo() {
super.printInfo(); // 呼叫父類別的 printInfo()
System.out.println("Student: " + this.name); // this 指的是子類別自己的 name
}
}

public class Main {
public static void main(String[] args) {
Student s = new Student();
s.printInfo();
}
}



其它 - 回傳練習

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class Person {
private String name;
private Integer age;

// 無參數建構子
public Person() {
this("匿名", 18);
}

// 只給年齡
public Person(Integer age) {
this("匿名", age);
}

// 只給名字
public Person(String name) {
this(name, 18);
}

// 全部給
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}

// 顯示資訊用的方法
public void printInfo() {
System.out.println("姓名:" + name + ",年齡:" + age);
}

// 主程式
public static void main(String[] args) {
Person p1 = new Person(); // 匿名, 18
Person p2 = new Person(25); // 匿名, 25
Person p3 = new Person("小明"); // 小明, 18
Person p4 = new Person("小美", 20); // 小美, 20

p1.printInfo();
p2.printInfo();
p3.printInfo();
p4.printInfo();
}
}



錯誤觀念澄清

❌錯誤觀念 ✅正確觀念
Java 不支援繼承 Java 支援單一繼承
子類別無法使用父類方法 只要沒被 private 修飾都能繼承
父類別的建構子不會執行 子類別建構子會自動先呼叫父類別建構子
方法覆寫時,回傳型別可以不同 覆寫時方法簽章必須相同



重點整理

  • 繼承讓子類別 extends 父類別,節省程式碼
  • 子類別能使用父類別的屬性與方法
  • 可以使用 @Override 改寫方法內容
  • super() 能呼叫父類別建構子與成員
  • 只有單一繼承,但可用**介面(interface)**實現多型(多種行為)