從 JavaScript 角度學 Python(24) - 繼承

前言

前一篇已經提前預告接下來將會講繼承了,所以這一篇當然就是會介紹繼承啦~(廢話)

繼承的概念

繼承是什麼呢?JavaScript 有嗎?JavaScript 是有的哦。

那麼簡單來講繼承的概念,假設是用人的角度來形容的話,你可以把它想像成有一個爸爸,然後他會有一個兒子(廢話),然後這個兒子會有爸爸的一些生物特徵,例如:可以爸爸眼睛瞳孔顏色是藍色的,所以兒子繼承下來的瞳孔顏色也就會是藍色的。

所以前面我們就簡單寫一個 JavaScript 的繼承版本稍微參考一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Father(pupil) {
this.pupil = pupil || '藍色'; // 瞳孔顏色
}

function Son(name) {
Father.call(this);
this.name = name; // 兒子的名字
}

Son.prototype = Object.create(Father.prototype);
Son.prototype.constructor = Son;

Son.prototype.eyeColor = function() {
console.log(this.name + ' 眼睛顏色是:' + this.pupil);
}

const ray = new Son('Ray');
ray.eyeColor(); // Ray 眼睛顏色是:藍色

透過上面簡單的範例,我們可以看到不管怎樣,兒子的眼睛顏色會是繼承來自爸爸的瞳孔顏色,而這就是一個非常簡單的繼承概念,如果你對於上面的程式碼不是那麼熟悉的話,我會建議你可以先閱讀我先前寫的筆記 繼承與原型鍊 的部分,因此這邊就不多著墨於這一塊,接下來就直接準備進入了解 Python 的繼承是如何撰寫囉~

但是這邊也可以簡單寫一次 JavaScript 的 ES6 class 版本的寫法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Father {
constructor(pupil) {
this.pupil = pupil || '藍色'; // 瞳孔顏色
}
}

class Son extends Father {
constructor(name) {
super()
this.name = name; // 兒子的名字
}
eyeColor() {
console.log(this.name + ' 眼睛顏色是:' + this.pupil);
}
}

const ray = new Son('Ray');
ray.eyeColor(); // Ray 眼睛顏色是:藍色

基本上你會看到 prototype 的寫法跟 class 的寫法有很明顯的不同,在語法上的撰寫也相對簡易很多,可是這邊要注意 JavaScript 依然是以原型為導向的語言class 只是一個語法糖而已,在底層實作上依然是 prototype 的概念。

class 讚讚

繼承

前面稍微回顧了 JavaScript 的繼承概念與寫法之後,接下來當然是拉回到 Python 中啦~

那 Python 中的繼承寫法會非常複雜嗎?其實並不會,這邊讓我們換一個練習範本,我們先用前面 JavaScript 的範本建立一個 class 出來:

1
2
3
class Father:
def __init__(self, pupil):
self.pupil = pupil or '藍色'

好,那接下來繼承該如何寫呢?

絕對是用 extends

不,絕對不是使用 extends 語法。

哈哈哈哈哈

Python 的繼承語法非常簡潔,只需要在 class 名稱後方加上括號並傳入要繼承的 class 名稱就可以了:

1
2
3
4
5
6
class Father:
def __init__(self, pupil):
self.pupil = pupil or '藍色'

class Son(Father):
pass

有沒有發現非常簡單呢?如果你不知道我寫 pass 的用途的話,建議你可以往前一篇看這邊就不解釋了。

那麼接下來讓我們直接補完 Son 的內容再繼續往下介紹:

1
2
3
4
5
6
7
8
9
10
class Father:
def __init__(self, pupil):
self.pupil = pupil or '藍色'

class Son(Father):
def __init__(self, name):
self.name = name

def eyeColor(self):
print(this.name + ' 眼睛顏色是:' + this.pupil)

這時候不用急著實例化 Son,基本上這一段是會出現一段錯誤訊息,也就是「AttributeError: 'Son' object has no attribute 'pupil'」的錯誤訊息,主要原因是因為當我們在子類別中使用 __init__ 方法時,是會覆蓋原有父類別的繼承 __init__,所以這邊我們必須重新將 Father 重新繼承回來,而重新繼承寫法其實有兩種,第一種就是是使用 __init__

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Father:
def __init__(self, pupil):
self.pupil = pupil or '藍色'

class Son(Father):
def __init__(self, name):
Father.__init__(self, '')
self.name = name

def eyeColor(self):
print(self.name + ' 眼睛顏色是:' + self.pupil)

ray = Son('Ray')
ray.eyeColor() # Ray 眼睛顏色是:藍色

這樣子上面這一段範例程式碼,就可正常的運作囉~

那另一種方式則是使用 super 的函式重新繼承:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Father:
def __init__(self, pupil):
self.pupil = pupil or '藍色'

class Son(Father):
def __init__(self, name):
super().__init__('')
self.name = name

def eyeColor(self):
print(self.name + ' 眼睛顏色是:' + self.pupil)

ray = Son('Ray')
ray.eyeColor() # Ray 眼睛顏色是:藍色

使用 super 函式的好處在於,你不用去撰寫父類別的名稱,它會自動去尋找你所傳入的副類別名稱,然後自動重新繼承父類別的屬性與函式。

那你看到這邊之後有沒有覺得 Python 與 JavaScript 的 class 是不是有相似之處呢?

這是 JavaScript 嗎?

那這一篇也算是到這邊結束了,主要是補完前一章節關於 class 的部分。

作者的話

因為工作的關係,自己時常很忙比較少在打掃家中,所以很仰賴小瓦機器人掃跟拖地,但是最近在幫小瓦機器人清理集塵盒的時候…

不小心把集塵盒捏爆了…囧

關於兔兔們

兔法無邊

Liker 讚賞 (拍手)

如果這一篇筆記文章對你有幫助,希望可以求點支持或 牡蠣 鼓勵 (ノД`)・゜・。

Liker 是一個按讚(拍手)的讚賞機制,每一篇文章最多可以按五下(拍手),按讚過程你是完全不用付費的(除非你想要每個月贊助我 :D),你只需要登入帳號就可以開始按讚。
而 Liker 會依據按讚數量分配獎金給創作者,所以如果你願意按個讚我會非常感謝你唷。

Google AD

撰寫一篇文章其實真的很花時間,如果你願意「關閉 Adblock (廣告阻擋器)」來支持我的話,我會非常感謝你 ヽ(・∀・)ノ