物件与类别 (object and class)

来建立几个物件吧

在上一篇文章当中,我们提到可以使用物件来模拟真实世界的事物,那麽我们就来尝试建立几个棒球选手的物件吧!

首先,我们建立一个叫做 shohei 的物件,当中有一个属性 name,以及一个方法 hit

const shohei = {
  name: 'shohei',
  hit: function () {
    console.log(`${this.name} can hit!`)
  }
}

接下来,让我们同样建立另外一个棒球选手物件 ohtani,拥有相同的属性与方法,只是名字不太一样

const ohtani = {
  name: 'ohtani',
  hit: function () {
    console.log(`${this.name} can hit!`)
  }
}

完成之後,我们就可以操作这些物件,譬如取得属性的值,或是呼叫方法:

shohei.name   // shohei
ohtani.name   // ohtani

shohei.hit()  // shohei can hit!
ohtani.hit()  // ohtani can hit!

用类别来建立物件

现在我们已经有两位棒球选手了,不过如果要打比赛的话,至少还要另外建立七位选手,也就是要重复这段程序码七次:

const xxx = {
  name: 'xxx',
  hit: function () {
    console.log(`${this.name} can hit!`)
  }
}

同时会发现,这些物件的属性、方法都一模一样,只差在属性 name 的值不一样。那麽我们可以建立一个像是蛋糕模的东西,帮我们快速产生许多一模一样的蛋糕(结果)吗?

在物件导向程序设计当中的确有这种东西,它就叫「类别」(class)。这里我们先跳过定义,先快速来实作一下。

首先,先建立一个叫做 BaseballPlayer 的类别,当中包含了 name 属性和 hit 方法。另外透过 constructor 来接收并指派创建物件时所输入的资讯。

class BaseballPlayer {
  name: string

  constructor(name: string) {
    this.name = name
  }

  hit() {
    console.log(`${this.name} can hit`)
  }
}

接下来,我们就可以使用 BaseballPlayer 类别来快速产生另外两个物件:

const ichiro = new BaseballPlayer('ichiro')
const shuzuki = new BaseballPlayer('shuzuki')

最後,就可以得到我们当初所期待的物件们

ichiro.hit()    // ichiro can hit!
suzuki.hit()    // huzuki can hit!

所以什麽是类别?

在程序设计当中,类别是一种程序码的范本,可以用来建立物件、描述当中的属性与方法,以及提供初始状态。

In object-oriented programming, a class is an extensible program-code-template for creating objects, providing initial values for state (member variables) and implementations of behavior (member functions or methods).

在刚刚 BaseballPlayer 这个类别的例子当中

class BaseballPlayer {
  name: string

  constructor(name: string) {
    this.name = name
  }

  hit() {
    console.log(`${this.name} can hit`)
  }
}

我们描述了一个属性 name、一个方法 hit,以及透过 constructor 提供初始状态。而透过类别所建立的物件,通常称作实例 (instance)。在刚刚的例子当中,ichirosuzuki 都是 BaseballPlayer 这个类别的实例。

反过来看,一个类别其实也提供了「规范」。以 BaseballPlayer 这个例子来说,它规范了 baseball players 所应该具备的属性和方法。

关於类别的「继承」

除了自己亲手建立一个新的类别之外,我们也可以透过「继承」的方式,让新的类别承接原有类别的属性或方法。

举例来说,我们希望建立一个游击手 (short stop) 的类别,他除了要有基本 baseball player 的属性和方法之外,还要新增一个 run 方法。所以这里我们建立 Shortstop 类别,然後透过 extends 语法来继承 BaseballPlayer

class Shortstop extends BaseballPlayer {
  run() {
    console.log(`${this.name} can run`)
  }
}

之後,我们就可以用这个新的类别,来建立一位游击手,一位又能打又能跑的棒球选手!

const jeter = new Shortstop('jeter')
jeter.hit()                            // jeter can hit
jeter.run()                            // jeter can run

为什麽要有类别?

类别除了能够帮助我们快速建立相同类型的物件(实例)之外,还带来了其他好处,像是

  • 当我们把「类似的事物」归类成一类之後,未来就能够很快的透过这个类别来建立这些事物
  • 如果已经有建立好的类别,那麽我们就可以直接使用,不需要自己建立物件、或重新打造一个类别
  • 如果要针对某一类的事物进行修改,那麽我们可以直接从类别下手修改

抽取类别

而因为有了「继承」这个特性,我们甚至可以将不同类别当中的相同属性或方法,抽取出来,建立一个 parent 类别,然後让其他 child 类别继承他的属性或方法。同样的方法,我们可以继续做下去,产生 parent's parent、parent's parent’s parent 类别等等。

这就很像生物学当中的「界门纲目科属种」的层层分类方式,以人来说,就被归类於下面这样的分类当中:

  • 界: 动物界
  • 门: 脊索动物门
  • 纲: 哺乳纲
  • 目: 灵长目
  • 科: 人科
  • 属: 人属
  • 种: 智人

而你、我都是「智人」这个类别的实例,继承了(包含了)人属当中所描述的特徵,也包含了更上层类别的特徵。

在生物学当中,我们透过这样分类法(林奈氏分类法)来整理世界上所有的生物,同样的我们也可以透过这种方式,来建立各种、层层的类别,来模拟世界上的事物。

如何分类?

但是,如果今天我们只是想要用程序打造一个待办清单的应用程序,其实不需要花这麽大的功夫去把所有世界上所有事物整理成各种类别,我们只要把跟待办清单应用程序相关的事物整理起来就行。

不过这时候就会有另外一个问题,那就是在面对一个新的问题或情境时,我们该如何分类?我们该建立哪些的类别呢?这个就留待我们後续讨论吧!


最後,分享一下一个有趣的影片


<<:  [Day18] NLP会用到的模型(二)-GRU

>>:  # Day3--向左走?向右走?再走一次?那些替你做决定的小事

全端入门Day29_後端程序撰写之一点点的Golang

昨天解释了Golang的hello world,今天要用Go来做一个localhost。 Golan...

[Day01] 前言:常见的前端实战技能有哪些?

Credit: https://lilly021.com/angular-vs-react-vs-...

D31 - 「来互相伤害啊!」:无聊我要见到血流成河

上竞技场就是要决斗阿,不然要干嘛。 来让人物发射武器!血流成河吧! 首先来回顾一下 D27 武器规划...

Day 03 - 行前说明 — 在 MVC & MVVM 的 UI 元件

相信网路上其实已经有不少文章在谈架构了,我的资历也尚浅,今天虽然会介绍架构,但是主要会侧重的点会是...

Day18 - (补上昨天程序码) + BBT介绍

大家好,我是长风青云。早起跟朋友约、下午无缝接轨去帮弟弟搬宿、晚上一回到家就开始做ppt和发片。累瘫...