以類別為基礎的語言 vs. 以原型為基礎的語言

以類別為基礎的語言 vs. 以原型為基礎的語言

以類別為基礎的語言,如 Java 和 C++,是以兩種不同實體的概念為根基︰類別(Class)和實體(Instance)。

  • 類別定義了所有的屬性(就 Java 的方法和欄位以及 C++ 的成員而論),刻劃出明確的物件集合。類別是抽象的事物,而不是任何他所刻劃的物件集合的實際成員。例如,Employee 類別可以代表所有職員的集合。
  • 實體從另一個角度來看就是類別的實際例證;也就是類別成員的其中一者。例如,Victoria 可以是 Employee 類別的實體,代表作為職員的獨特個體。實體恰好有親類別的屬性(且不多也不少)。

以原型為基礎的語言,如 JavaScript,並沒有這些分別︰他簡單到只有物件。以原型為基礎的語言具有原型物件的概念。物件被當作模板來使用,從中取得最初的屬性以提供給新物件。不論是在你建立物件或執行時期的時候,任何物件都可以指定他自己的屬性。此外,任何物件都可以作為其他物件的原型而連繫起來,讓第二個物件共用第一個物件的屬性。

類別的定義

在以類別為基礎的語言中,你會在獨立的類別定義中定義類別。在這些定義中,你可以指定稱為建構子的特殊方法,用來建立類別的實體。建構子方法可以為實體的屬性指定初始值,並進行在建立時期的其他適當處理。你會使用 new 運算子配合建構子方法來建立類別的實體。

JavaScript 遵從類似的模型,但是建構子和其他類別的定義並沒有分別。取而代之,你會定義建構子函數來建立帶有特定初始值的一組屬性和值的物件。任何的 JavaScript 函數都可以用作建構子。你會使用 new 運算子配合建構子函數來建立新的物件。

子類別和繼承

在以類別為基礎的語言中,你會建立出類別定義整體的類別階層。在類別的定義中,你可以把新的類別指定為另一個既存類別的子類別。這個子類別會繼承親類別所有的屬性,也可以另外加入新的屬性或修改繼承下來的。例如,假定 Employee 類別只含有 name 和 dept 屬性,而 Manager 是 Employee 的子類別,且加入了 reports 屬性。在這個情況下,Manager 類別的實體將具有全部的三個屬性︰name、dept、reports。

JavaScript 可讓你把任意的建構子函數和原型物件連結在一起,以此實現繼承。因此,你可以準確的建立出 Employee 和 Manager 的範例,但是你會使用有點不一樣的術語。首先,你會定義 Employee 的建構子函數,指定 name 和 dept 屬性。接著,你會定義 Manager 的建構子函數,指定 reports 屬性。最後,你會把新的 Employee 物件作為原型代入給 Manager 的建構子函數。然後,當你建立新的 Manager 的時候,他就會從 Employee 物件繼承 name 和 dept 屬性。

屬性的加入和移除

在以類別為基礎的語言中,你通常會在編譯時期建立類別,然後你會在編譯時期或執行時期實體化類別的實體。在你定義了類別以後,你就不能改變類別的屬性的類型或數目。然而在JavaScript 中,你可以在執行時期加入或移除任何物件的屬性。如果你把屬性加入到用作為一整群物件的原型的物件裡,使用同一個原型的物件也會得到新的屬性。

不同點的摘要

下表給出了這些不同點的簡短摘要。本章的剩餘部分描述了使用 JavaScript 的建構子和原型來建立物件的階層,並和 Java 的做法來做比較。

以類別為基礎 (Java) 以原型為基礎 (JavaScript)
類別和實體這兩者有分別。 所有的物件都是實體。
使用類別定義來定義類別;使用建構子方法來把類別實體化。 使用建構子函數來定義並建立一整群物件。
使用 new 運算子來建立單一的物件。 相同。
使用類別定義來建構物件的階層,用以定義既存類別的子類。 藉由代入,把作為原型的物件和建構子函數連結起來,來建構出物件的階層。
藉由遵從類別鏈來繼承屬性。 藉由遵從原型鏈來繼承屬性。
類別定義指定了類別的所有實體的所有屬性。不能在執行時期動態的加入屬性。 建構子函數或原型指定並初始化了一系列屬性。可以給單獨的物件或一整組物件來動態的加入或移除屬性。

Document Tags and Contributors

Contributors to this page: happysadman
最近更新: happysadman,