从 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 的部分。

作者的话

因为工作的关系,自己时常很忙比较少在打扫家中,所以很仰赖小瓦机器人扫跟拖地,但是最近在帮小瓦机器人清理集尘盒的时候...

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

关於兔兔们

兔法无边


<<:  大数据平台:分散式协调

>>:  [Day-25] R语言 - 分群应用(五) 分群预测 - 资料清洗 ( data cleaning in R.Studio )

EP03 - aws cli configuration 与 terraform 配置

准备工具 Visual Studio Code 或自己习惯的 IDE 可用的 AWS 帐户 目标 昨...

2022/1/2 更新

1.Grid_Optimizer: 原本使用4年资料回测,改成5年,00646改00662。 2.G...

【Day 26】S3 on AWS Outpost 限制与建置流程

tags: 铁人赛 AWS S3 Outposts S3 Bucket 前言 昨天我们成功把 K8S...

Day22-Vuex简介

终於到了vuex拉!! Day10时有说之後要来研究,没想到这一天这麽快就到来,那就进入正题吧。 为...

第十八天:用 Plugin 扩充 TeamCity

昨天提到 TeamCity 支援几个不同的通知频道,可以在建置任务成功或失败的时候通知我们。不过现在...