iT邦幫忙

2021 iThome 鐵人賽

DAY 3
0

來建立幾個物件吧

在上一篇文章當中,我們提到可以使用物件來模擬真實世界的事物,那麼我們就來嘗試建立幾個棒球選手的物件吧!

首先,我們建立一個叫做 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)。在剛剛的例子當中,ichiro 和 suzuki 都是 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 類別等等。

這就很像生物學當中的「界門綱目科屬種」的層層分類方式,以人來說,就被歸類於下面這樣的分類當中:

  • 界: 動物界
  • 門: 脊索動物門
  • 綱: 哺乳綱
  • 目: 靈長目
  • 科: 人科
  • 屬: 人屬
  • 種: 智人

而你、我都是「智人」這個類別的實例,繼承了(包含了)人屬當中所描述的特徵,也包含了更上層類別的特徵。

在生物學當中,我們透過這樣分類法(林奈氏分類法)來整理世界上所有的生物,同樣的我們也可以透過這種方式,來建立各種、層層的類別,來模擬世界上的事物。

如何分類?

但是,如果今天我們只是想要用程式打造一個待辦清單的應用程式,其實不需要花這麼大的功夫去把所有世界上所有事物整理成各種類別,我們只要把跟待辦清單應用程式相關的事物整理起來就行。

不過這時候就會有另外一個問題,那就是在面對一個新的問題或情境時,我們該如何分類?我們該建立哪些的類別呢?這個就留待我們後續討論吧!


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

Yes


上一篇
什麼是物件導向程式設計 (Object-oriented programming)
下一篇
抽象類別與介面 (1)
系列文
幫自己搞懂物件導向和設計模式 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言