物件導向之繼承

如題。

簡述

簡單來說就是「繼承某個 class 的屬性和方法」。

假設我有一個 Person 的 class,會有名稱和年齡,然後會打招呼。

1
2
3
4
5
6
7
8
9
10
11
class Person {
constructor (name, age) {
this.name = name;
this.age = age;
}
log () {
console.log(this.name + ', ' + this.age);
}
}
const peanu = new Person('peanu', 23);
peanu.log(); // peanu, 23

現在我希望有一個黑人,一樣具備 Person 的特性(名稱、年齡、打招呼),但要多一項技能是「唱 Rap」,這時候就應該利用「繼承」的方式來建立,而不是重新寫一個幾乎相同的 class

1
2
3
4
5
6
7
8
class BlackPerson extends Person {
rap() {
console.log('yoyoyo my name is ' + this.name);
}
}
const blackMan = new BlackPerson('blackMan', 30);
blackMan.log(); // blackMan, 30
blackMan.rap(); // yoyoyo my name is blackMan

注意,這裡用了 extends 來繼承 Person 的資訊,所以即便 BlackPerson 中沒有寫 constructor,也一樣具備 nameage 這兩個屬性,而且也可以用 log 方法。

除了繼承以外,我們也幫它加了一個 rap 方法。所以只要是從 BlackPerson 生出來的 instance,都會具備 rap 的能力。

如果我想在繼承的 class 上使用 constructor 怎麼辦?

以剛剛的例子來說,如果我希望幫 BlackPerson 加上性別,我可能直覺會這樣寫:

1
2
3
4
5
6
7
8
9
10
11
12
13
class BlackPerson extends Person {
constructor (gender) {
// 加上一個新的 gender 屬性
this.gender = gender;
}
rap () {
console.log('yoyoyo my name is ' + this.name + ', and my gender is ' + this.gender);
}
}
// 建立 instance
const blackMan = new BlackPerson('blackMan', 30, 'man');
// 預期:yoyoyo my name is blackMan, and my gender is man
blackMan.rap();

但這樣會得到錯誤:

1
2
ReferenceError: Must call super constructor in derived class before accessing 'this' or ret
urning from derived constructor

簡單來說,要在繼承的 class 上設定 constructor 之前,得先呼叫 super 這個 function。先執行原本 Person 的 constructor,接著再執行 BlackPerson 的 constructor,所以應該要這樣寫:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class BlackPerson extends Person {
constructor (name, age, gender) {
// 呼叫 super 並傳入參數
super(name, age);
// super 執行完後才建立新的 gender
this.gender = gender;
}
rap () {
console.log('yoyoyo my name is ' + this.name + ', and my gender is ' + this.gender);
}
}
// 建立 instance
const blackMan = new BlackPerson('blackMan', 30, 'man');
// yoyoyo my name is blackMan, and my gender is man
blackMan.rap();

總而言之,一定要記得先執行 super,這樣才不會出錯。

重新理解 this 的值 new 實際上在做什麼?
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×