有鑑於,被朋友問到講得哩哩落落,寫個小 memo 給自己
本文著重在比較 Java class-based 與 JavaScript protoytpe-based
前言
OOP(物件導向程式)是什麼?
OOP = Object-oriented programming = 物件導向程式設計,是一種以物件設計程式設計的設計方法。
希望可以透過三大特性:繼承、封裝、多型,讓程式碼減少重複代碼並彈性地擴充,以及能零活調用組裝 。
遵守OOP開發原則(SOLID) 也能寫出更好維護的軟體。
本文以繼承特性為討論物件導向的範圍。
各語言如何支援物件導向?
class-based programming: Java
Java 是靜態(編譯)、強型別語言
學習 Java 的基礎:
- Everything in Java is an object
- "Class(類別)是 Object(物件)的藍圖,物件是類別的 Instance(實例)"
在 Java 中的物件必須先定義出 Class 才能夠創造出物件,而程式的運作需要透過 Object (Class Instance)。
從 Hello World 的範例裡看到,一行 print 指令需要被寫在一個 HelloWorld Class 檔案裡,編譯後執行。
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello! World!");
}
}
Java 透過 new 與 extends 關鍵字來做到類別實例與繼承,Object Class 是所有的 Class 共同繼承的源頭。
// Class
public class Hero extends GameObject{
public String name;
public Hero(String name) {
this.name = name;
}
}
// Object
Hero heroAria = new Hero(Aria);
Hero heroBrant = new Hero(Brant);
我們已經為所有的 Hero 類別都定義了 name 屬性,如果之後想要修改所有物件的 name 屬性,例如加上 HERO 在名字前,就不需要一一修改。
這裡繼承的對象 class,沒有談到實體化的物件。
參考
- Java 學習手冊
prototype-based programming: JavaScript
JavaScript 是動態(直譯/腳本)、弱型別語言
JavaScript 支援 OOP,也支援 FP(Functional Programming)
JavaScript 中則是使用 Prototype(原型)為基礎設計。
OOP 是一種設計典範,通常用於開發系統軟體。
因此,JavaScript、Python 這樣的腳本語言,OOP 的概念不是入門學習時首要的學習目標,許多教材會將 OOP 放在進階觀念裡。
回到繼承,JavaScript 是腳本語言,所以它並不用 Class 的方式實現繼承,而是透過原型鍊查找物件屬性。
講到繼承,JavaScript 就只有一個建構子:物件。每個物件都有一個連著其他原型(prototype)的私有屬性(private property)物件。原型物件也有著自己的原型,於是原型物件就這樣鏈結,直到撞見 null 為止:null 在定義裡沒有原型、也是原型鏈(prototype chain)的最後一個鏈結。
我從 Java 進入 JavaScript 在學習 prototype 的時候曾產生混亂,不明白為什麼用建構式定義物件時使用 function 關鍵字、為什麼 new 一個函式會跑出物件。(因為我們定義的這個函式是個建構子)
傳統的 OOP 都是先定義了類別,接著在建立物件實例之後,在類型上定義的所有屬性與函式均複製到此實例。但 JavaScript 不會複製這些屬性與函式,卻是在物件實例與其建構子之間設定連結 (原型鍊中的連結),只要順著原型鍊就能在建構子之中找到屬性與函式。
MDN 物件原型
function f() {
return 2;
}
// 從 Function.prototype 繼承的函式,含有諸如 call、bind……之類的方法
// f ---> Function.prototype ---> Object.prototype ---> null
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function(v) {
this.vertices.push(v);
}
};
var g = new Graph();
// g 是個有著「vertices」與「edges」屬性的物件。
// 在執行 new Graph() 時 g.[[Prototype]] 是 Graph.prototype 的值。
累了,寫到這裡好了。
有誤歡迎糾正。