原型程式設計

原型程式設計

原型程式設計(英語:prototype-based programming)或稱為原型程式設計、原型編程,是面向對象編程的子系統和一種方式。在原型編程中,類不是實時的,而且行為重用(通常認為繼承自基於類的語言)是通過複製已經存在的原型對象的過程實現的。這個模型一般被認為是 classless、面向原型、或者是基於實例的編程。

基本介紹

  • 中文名:原型程式設計
  • 外文名:prototype-based programming
  • 又稱:原型編程
  • 本質:面向對象編程的子系統和一種方式
簡介,與類別基礎編程的比較,對象構造,委託,關聯,評價,相關語言,

簡介

原型編程最初的(也是最經典的)例子是程式語言 Self,它是由 David Ungar 和 Randall Smith 開發的。但是 classless 編程方式最近變得越來越受歡迎,並且被 JavaScript、Squeak (當使用觀察者框架操作 Morphic 組件時)、Cecil、NewtonScript、Io、MOO、REBOL 還有一些其他的程式語言所採納。

與類別基礎編程的比較

在類別基礎編程當中,對象總共有兩種類型。類定義了對象的基本布局和函式特性,而接口是“可以使用的”對象,它基於特定類的樣式。在此模型中,類表現為行為和結構的集合,就接口持有對象的數據而言,對所有接口來說是相同的。區分規則因而首先是基於結構和行為,而後是狀態。
原型編程的主張者經常爭論說基於類的語言提倡使用一個關注分類和類之間關係開發模型。與此相對,原型編程看起來提倡程式設計師關注一系列對象實例的行為,而之後才關心如何將這些對象劃分到最近的使用方式相似的原型對象,而不是分成類。因為如此,很多基於原型的系統提倡運行時原型的修改,而只有極少數基於類的面向對象系統(比如第一個動態面向對象的系統 Smalltalk)允許類在程式運行時被修改。
原型編程常與認知心理學的特定思想流派有關,同樣強調prototypes 和 exemplars 作為學習過程中的關鍵字。
考慮到絕大多數基於原型的系統是基於解釋性的和動態類型程式語言,這裡要重點指出的是靜態類型語言實現基於原型從技術上是可行的。用基於原型編程描述的 Omega 語言就是這樣系統的一個例子。儘管根據 Omega 網站所述,Omega 也不是完全的靜態,但是可能的時候,它的編譯器有時會使用靜態綁定來改進程式的效率。

對象構造

在基於類的語言中,一個新的實例通過類構造器和構造器可選的參數來構造,結果實例由類選定的行為和布局建立模型。在基於原型的系統中構造對象有兩種方法,通過複製已有的對象 或者通過擴展 nihilo(空的)對象創建,因為大多數系統提供了不同的複製方法,擴展 nihilo 對象的方式鮮為人知。
提供擴展 nihilo 對象創建的系統允許對象從空白中創建而無需從已有的原型中複製。這樣的系統提供特殊的文法用以指定新對象的行為和屬性,無須參考已存在的對象。在很多原型語言中,通常有一個 Object 原型,其中有普遍需要的方法。它被用作所有其它對象的最終原型。擴展 nihilo 對象創建可以保證新對象不會被頂級對象的命名空間污染。(在JavaScript中,可以利用null原型來做到, i.e. Object.create(null))。
Cloning 指一個新對象通過複製一個已經存在的對象(就是他的原型)來構造自己的過程。於是新的對象擁有原來對象的所有屬性,從這一點出發新對象的屬性可以被修改。在某些系統中,子對象持有一個到它原型的直接連結(經由授權或類似方式)。並且原型的改變同樣會導致它的副本的變化。其他系統中,如類 Forth 的程式語言,Kevo 在此情況下不傳播原型的改變,而遵循一個更加連續的模型,其中被複製的對象改變不會通過他的副本傳播。
// Example of true prototypal inheritance style// in JavaScript. // "ex nihilo" object creation using the literal// object notation {}.var foo = {name: "foo", one: 1, two: 2}; // Another "ex nihilo" object.var bar = {three: 3}; // Gecko and Webkit JavaScript engines can directly// manipulate the internal prototype link.// For the sake of simplicity, let us pretend// that the following line works regardless of the// engine used:bar.__proto__ = foo; // foo is now the prototype of bar. // If we try to access foo's properties from bar// from now on, we'll succeed.bar.one // Resolves to 1. // The child object's properties are also accessible.bar.three // Resolves to 3. // Own properties shadow prototype propertiesbar.name = "bar";foo.name; // unaffected, resolves to "foo"bar.name; // Resolves to "bar"
下面是個在 JavaScript 1.8.5 以上版本的例子
var foo = {one: 1, two: 2}; // bar.[[ prototype ]] = foovar bar = Object.create( foo ); bar.three = 3; bar.one; // 1bar.two; // 2bar.three; // 3

委託

在使用委託的基於原型的語言中,運行時語言可以僅僅通過循著一個序列的指針直到找到匹配這樣的方式來定位屬性或者尋找尋找正確的數據。所有這些建立行為共享的行為 需要的是委託指針。不象是基於類的面向對象語言中類和接口的關係,原型和他的分支之間的關係並不要求子對象有相似的記憶體結構,因為如此,子對象可以繼續修改和...而無須像基於類的系統那樣整理結構。還有一個要提到的地方是,不僅僅是數據,方法也能被修改。因為這個原因,大多數基於類型的語言把數據和方法提作“slots”。

關聯

在純粹的原型,又被稱作 concatenative 原型(以 Kevo 語言為例)中沒有到被複製的原型對象的指針或連結。原型對象以重新給定名字(或引用)的方式被確實的複製了。這個過程類似於生物學上的分裂,屬性和方法被原樣複製。
這樣做的好處包括對象的作者可以修改這份副本而無須擔心對此父類的其他子類產生副作用。進一步的優點是查找屬性運算的消耗同授權相比大大降低了,授權查找必須遍歷整個委託鏈才能判定不存在。
Concatenative 的壞處包括傳播變化到整個系統的難度;如果一個變化作用到某個原型,它不會立即或者自動的對它的所有副本生效。然而Kevo提供了額外的在對象系統中傳播變化的方式。這種方式是基於他們的相似性(所謂的 family 相似)而非像委託模型具有代表性的那樣源自分類學。
另外一個壞處是在這個模型的大多數自然的實現下,每一個副本上都有額外的記憶體被浪費掉了(相對委託模型而言),因為副本和原型之間有相同的部分存在。然而,在共享的實現和後台數據中提供 concatenative 行為的編程編程是可行的。這種做法為 Kevo 所遵從。

評價

那些經常批評基於原型系統而支持基於類的對象模型的人通常有類似靜態類型系統相對於動態類型系統的擔心。通常這些擔心是:正確性、安全性、可預測性以及效率。
在前三點上,類可以看作和類型等效(多數靜態語言遵守此規則)而且提供保證他們實例的契約,而對這些實例的使用者保證特定場景中的行為。
在最後一點上,效率,類的聲明簡化了編譯器的組織,允許開發高效的方法以及實例變數查找。對Self語言來說,大多開發時間都消耗在開發、編譯以及解釋技術用以改進基於原型的系統相對於基於類的系統。舉例來說 Lisaac 產生的代碼速度幾乎跟C一樣快。測試是由 MPEG-2 編碼器的 Lisaac 版本得出的,它由一個C語言版本複製而來。測試顯示,Lisaac 版本比 C 版本慢1.9%,但代碼行數少了37%。然而C語言並非面向對象語言,而是一個過程式語言。Lisaac 跟 C++ 版本相比可能更說明問題。
最普遍的對基於原型的語言的批評來自不喜歡它的軟體開發者社區,僅管有 JavaScript 的人氣和市場。對基於原型系統的了解程度似乎因為JavaScript 框架的廣泛套用以及 JavaScript 針對 Web 2.0的複雜套用而改變。很可能由於這些原因,在 ECMAScript 標準的第四版開始尋求使 JavaScript 提供基於類的構造,且ECMAScript 第六版有提供"class"(類)作為原有的原型架構之上的語法糖,提供建構物件與處理繼承時的另一種語法。

相關語言

Ioke
Lisaac
Logtalk
MOO
Neko
Obliq
Object Lisp
Omega
OpenLaszlo
Perl, with the Class::Prototyped module
R, with the proto package
Seph
SmartFrog
TADS
Tclwith snit extension

相關詞條

熱門詞條

聯絡我們