iT邦幫忙

2021 iThome 鐵人賽

DAY 24
1
Software Development

從 JavaScript 角度學 Python系列 第 24

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

前言

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

繼承的概念

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

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

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

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 版本的寫法:

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 的概念。

https://ithelp.ithome.com.tw/upload/images/20210923/20119486ymBgTDjIS9.png

繼承

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

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

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

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

https://ithelp.ithome.com.tw/upload/images/20210923/20119486z8DcC7ZAki.png

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

https://ithelp.ithome.com.tw/upload/images/20210923/20119486jISsvDP4jm.png

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

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

class Son(Father):
  pass

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

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

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__

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 的函式重新繼承:

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 是不是有相似之處呢?

https://ithelp.ithome.com.tw/upload/images/20210923/20119486iYai2CqqKK.png

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

作者的話

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

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

關於兔兔們

兔法無邊


上一篇
從 JavaScript 角度學 Python(23) - Class
下一篇
從 JavaScript 角度學 Python(25) - 例外處理
系列文
從 JavaScript 角度學 Python31

尚未有邦友留言

立即登入留言