2008-12-22 49 views
10

我來自類對象方向語言,最近我一直在學習那些花哨的動態語言(JavaScript,Python和Lua),我想了解如何在這些語言中使用OO的一些提示。瞭解這種方法的缺陷和缺點以及與傳統面向對象相比的優勢將是有用的。基於原型的面向對象。黃金三鏢客?

我得到的一般概念是,基於原型的面向對象基本上是用對象編程,但沒有關於如何使用它們的標準,而在正常的面向對象中,有一個固定的預定義方式來製作和使用對象。

總之,什麼是好的,壞的和這種方法的醜陋的部分?

+0

「類面嚮對象語言」 - 你可以提供一個例子語言還是兩個? 「傳統面向對象」 - 你能提供一個或兩個示例語言嗎? – 2008-12-22 02:53:27

+0

我會假設:原型OO - Javascript,傳統OO - 大多數其他OO語言。 我會把Python當作傳統的面向對象的方式(儘管如果需要的話,你可以使它像一個原型OO語言一樣)。 – Dan 2008-12-22 10:26:23

回答

13

基於原型的OO本身很不適合靜態類型檢查,有些人可能認爲這是不好的或醜陋的東西。基於原型的OO 確實有創建新對象的標準方式,你克隆和修改現有對象。您也可以建廠等

我覺得人最喜歡(「好」)是一種基於原型的OO非常輕巧靈活,提供非常高的功率重量比

對於關於如何使用基於原型的OO的提示,一個很好的起點是關於The Power of Simplicity的原始Self文件。

0

好吧,首先,原型模式是不是在現實中所有的不同; Smalltalk使用類似的方案;該類是具有類方法的對象。

從類POV看,一個類實際上是具有相同數據的對象的等價類,以及所有相同的方法;你可以看看爲原型添加一個方法來創建一個新的子類。

實現很簡單,但是很難做有效的類型檢查。

7

爲了節省帶寬,此處鏈接到my answer on "How can I emulate 「classes」 in JavaScript? (with or without a third-party library)"。它包含更多的參考資料以及示例。

簡短回答:JavaScript的原型OO的核心是代表團。在這種風格相同的「類」的OOP不同的對象可以委託的方法和屬性的處理,以相同的原型(通常是一些第三對象):

var foo = { 
    property: 42, 
    inc: function(){ 
     ++this.counter; 
    }, 
    dec: function(){ 
     --this.counter; 
    } 
}; 
// Note: foo does not define `counter`. 

讓我們創建一個對象的構造函數以foo作爲原型。實際上,所有未處理的內容都將委託給foo。

var Bar = function(){ 
    this.counter = 0; 
}; 
Bar.prototype = foo; // This is how we set up the delegation. 

// Some people refer to Bar (a constructor function) as "class". 

var bar = new Bar(); 

console.log(bar.counter); // 0 --- Comes from bar itself 
console.log(bar.property); // 42 --- Not defined in bar, comes from foo 

bar.inc(); // Not defined in bar => delegated to foo 
bar.inc(); 
bar.dec(); // Not defined in bar => delegated to foo 
// Note: foo.inc() and foo.dec() are called but this === bar 
// that is why bar is modified, not foo. 

console.log(bar.counter); // 1 --- Comes from bar itself 

讓我們直接定義inc()上欄:

bar.inc = function(){ 
    this.counter = 42; 
}; 

bar.inc(); // Defined in bar => calling it directly. 
      // foo.inc() is not even called. 
console.log(bar.counter); // 42 --- Comes from bar 

設置單繼承鏈:

var Baz = function(){ 
    this.counter = 99; 
}; 
Baz.protype = new Bar(); 

var baz = new Baz(); 

console.log(baz.counter); // 99 
baz.inc(); 
console.log(baz.counter); // 100 

console.log(baz instanceof Baz); // true 
console.log(baz instanceof Bar); // true 
console.log(baz instanceof Object); // true 

整潔的,是吧?

1

古典繼承固有的缺陷在靈活性方面,因爲我們是在說「這個目標是這種類型的,沒有其他的。」有些語言介紹多重繼承,以緩解這一點,但多重繼承有自己的缺陷,所以純​​的組合超過繼承(其中,在靜態類型語言,是一個運行時而非編譯時機構)的好處變得清晰起來。

以構圖的概念來此「純粹」的層面上,我們可以用靜態敲字完全消除傳統的繼承。通過在運行時組合對象並將它們用作藍圖(原型方法),我們不需要過多地關注通過繼承過於緊密的裝箱對象,也不用爲多重繼承方法固有的問題負擔自己。

所以原型手段更加靈活的開發模塊。

當然,這是另外一回事地說很容易,而不靜態類型發展。海事組織,事實並非如此。