「繼承」是物件導向程式設計中一個重要也是核心的觀念,動詞原文為 inherit 。雖然 inherit 在英文的意思泛指從什麼得到什麼,用作中文「繼承」說得通,也能用作「遺傳」。然而中文的「繼承」隱含某物不再,另物將起的意思,譬如「我繼承某某的精神」,雖然某某不見得已死,未來將要付出努力的卻是我而非某某。因而這裡的意思中文用「遺傳」比較恰當,子代會從親代遺傳某些生物特性,子代與親代也會並存一段時間,這就沒有某物不再的意含了。然而這裡我們仍沿用程式設計常用的「繼承」一詞,但仍提出意見以免讀者混淆。
舉例如下
function run() {
var c = document.getElementById("content");
var n1 = document.createElement("p");
var n2 = document.createElement("p");
var n3 = document.createElement("p");
var n4 = document.createElement("p");
var n5 = document.createElement("p");
var n6 = document.createElement("p");
var t1 = new Elephant();
var t2 = new Elephant();
var t3 = new Elephant();
var t4 = t1.speak();
var t5 = t2.speak();
var t6 = t3.speak();
n1.appendChild(document.createTextNode(t1));
c.appendChild(n1);
n2.appendChild(document.createTextNode(t2));
c.appendChild(n2);
n3.appendChild(document.createTextNode(t3));
c.appendChild(n3);
n4.appendChild(document.createTextNode(t4));
c.appendChild(n4);
n5.appendChild(document.createTextNode(t5));
c.appendChild(n5);
n6.appendChild(document.createTextNode(t6));
c.appendChild(n6);
}
function Animal() {
this.age = 0;
this.weight = 0;
}
Animal.prototype.speak = function() {
return "哈囉,我已經" + this.age + "歲,有" + this.weight + "公斤重"
}
function Elephant() {
this.wname = "nobody";
}
Elephant.prototype = new Animal;
/* 《程式語言教學誌》的範例程式
http://pydoing.blogspot.com/
檔名:herit01.js
功能:示範 JavaScript 程式
作者:張凱慶
時間:西元 2010 年 11 月 */利用以下的 HTML 文件開啟
<html>
<head>
<title>JavaScript Demo</title>
<script src="herit01.js" type="text/javascript"></script>
</head>
<body>
<input id="b" type="button" value="RUN" onclick="run();">
<div id="content"></div>
</body>
</html>
<!-- 《程式語言教學誌》的範例程式
http://pydoing.blogspot.com/
檔名:herit01.html
功能:示範 JavaScript 程式
作者:張凱慶
時間:西元 2010 年 11 月 -->執行結果如下

我們在第 31 行定義了 Animal 物件的建構子函數 (constructor function) ,並且定義了一個 speak() 方法
function Animal() {
this.age = 0;
this.weight = 0;
}
Animal.prototype.speak = function() {
return "哈囉,我已經" + this.age + "歲,有" + this.weight + "公斤重"
}然後在第 39 行定義另一個 Elephant 物件
function Elephant() {
this.wname = "nobody";
}
Elephant.prototype = new Animal;繼承定義在第 42 行
Elephant.prototype = new Animal;
我們將 Elephant 物件的 prototype 屬性指派一個新的 Animal ,因此 Elephant 物件得以繼承 Animal 的屬性及方法,所以 run() 函數 (function) 中所新建的三個 Elephant 物件,可以呼叫執行 speak() 方法 。
然而上面的提供的繼承寫法並不具有彈性,屬性直接提供預設值。以下的寫法在建構子函數中可以提供參數 (parameter)
function run() {
var c = document.getElementById("content");
var n1 = document.createElement("p");
var n2 = document.createElement("p");
var n3 = document.createElement("p");
var n4 = document.createElement("p");
var n5 = document.createElement("p");
var n6 = document.createElement("p");
var t1 = new Elephant(98, 3000, "林旺");
var t2 = new Elephant(52, 2456, "伊芙");
var t3 = new Elephant(12, 1300, "小黑");
var t4 = t1.speak();
var t5 = t2.speak();
var t6 = t3.speak();
n1.appendChild(document.createTextNode(t1));
c.appendChild(n1);
n2.appendChild(document.createTextNode(t2));
c.appendChild(n2);
n3.appendChild(document.createTextNode(t3));
c.appendChild(n3);
n4.appendChild(document.createTextNode(t4));
c.appendChild(n4);
n5.appendChild(document.createTextNode(t5));
c.appendChild(n5);
n6.appendChild(document.createTextNode(t6));
c.appendChild(n6);
}
function Animal(age, weight) {
this.age = age || 0;
this.weight = weight || 0;
}
Animal.prototype.speak = function() {
return "哈囉,我已經" + this.age + "歲,有" + this.weight + "公斤重"
}
function Elephant(age, weight, wname) {
this.base = Animal;
this.base(age, weight);
this.wname = wname || "nobody";
}
Elephant.prototype.speak = function() {
return "我的名字是" + this.wname + "已經" + this.age + "歲"
}
/* 《程式語言教學誌》的範例程式
http://pydoing.blogspot.com/
檔名:herit02.js
功能:示範 JavaScript 程式
作者:張凱慶
時間:西元 2010 年 11 月 */利用以下的 HTML 文件開啟
<html>
<head>
<title>JavaScript Demo</title>
<script src="herit02.js" type="text/javascript"></script>
</head>
<body>
<input id="b" type="button" value="RUN" onclick="run();">
<div id="content"></div>
</body>
</html>
<!-- 《程式語言教學誌》的範例程式
http://pydoing.blogspot.com/
檔名:herit02.html
功能:示範 JavaScript 程式
作者:張凱慶
時間:西元 2010 年 11 月 -->執行結果如下

我們提供兩個參數給 Animal() ,其中
this.age = age || 0; this.weight = weight || 0;
參數會被指派給屬性,這裡連用邏輯或運算子 (operator) ,表示若沒有提供參數,便將 || 之後的預設值指派給屬性。
Elephant 的建構子函數定義在第 39 行
function Elephant(age, weight, wname) {
this.base = Animal;
this.base(age, weight);
this.wname = wname || "nobody";
}
Elephant.prototype.speak = function() {
return "我的名字是" + this.wname + "已經" + this.age + "歲"
}Elephant 多一個 base 屬性,其為 Animal ,然後利用 base 呼叫 Animal 的建構子函數,使 Elephant 繼承 Animal 的屬性,最後我們利用物件的 prototype 屬性動態增加 speak() 方法。
注意這裡的 prototype 是屬於動態增加的方式,如果是用 prototype 來繼承,利用 prototype 定義的方法都會被繼承下來。上例中我們利用的是 base 來繼承屬性,因此 Animal 用 prototype 定義的 speak() 並不會被繼承。
| 中英文術語對照 | |
|---|---|
| 原型基礎 | prototype-based |
| 物件導向程式設計 | object-oriented programming, OOP |
| 物件 | object |
| 繼承 | inheritance |
| 屬性 | attribute |
| 方法 | method |
| 建構子函數 | constructor function |
| 函數 | function |
| 參數 | parameter |
| 運算子 | operator |
沒有留言:
張貼留言