2013-08-29 31 views
1

說我有以下對象類型:JavaScript的 - 特別多繼承

var Positionable = function() { }; 
Positionable.prototype.x = 0; 
Positionable.prototype.y = 0; 

var Sizable = function() { }; 
Sizable.prototype.w = 0; 
Sizable.prototype.h = 0; 

var Fadable = function() { }; 
Fadable.prototype.a = 0; 

我想有一個功能,讓我創造條件,從其他幾種類型的繼承子類型。例如,我可以創建一個類型爲Rectangle,它將繼承PositionnableSizable

我所能鏈原型:

var Rectangle = function() { }; 
Sizable.prototype = new Positionable; 
Rectangle.prototype = new Sizable; 

但我不喜歡這種方法FO兩個原因:

  • 它會導致可調整大小從Positionable繼承,這意味着,如果我想另一個類型是可變的而不是Positionable,我做不到;

  • 這意味着一個Sizable對象也是Positionnable,其語義上是不好的,因爲沒有理由爲Sizable對象是Positionnable,而不是其他方式。

所以,我首先想到的關於合併的原型,假設我有一個函數void merge(type dst, type src, bool overwrite),迴路我會簡單地合併每個基類的原型到子類的原型。這不會創建一個鏈(這是我想如上所述)

但是這會導致另一個問題:因爲我沒有使用新的基礎構造函數不會被調用。所以我想知道,有沒有辦法也可以合併構造函數?例如,如果我可以訪問和引用基礎構造函數,我可以將這些基礎構造函數存儲在一個數組中,併爲子類型構造函數分配一個函數來調用每個構造函數。

我怎麼能這樣做與構造函數?或者,也許有另一種方式?

感謝您的幫助!

回答

2

由於JavaScript不支持多重繼承,因此您必須解析爲mixins。這就像你說的,你必須將其中一個原型的方法複製到子原型。

應該在子構造函數中調用構造函數。這裏有一個例子:

參見:Benefits of using `Object.create` for inheritance


function mixin(Target) { 
    var args = arguments; 

    // merge prototypes 
    for(var i = 1; i < args.length; i++) { 
     merge(Target.prototype, args[i].prototype); 
    } 

    // a new constructor function which calls all 
    // the passed constructor functions 
    var F = function() { 
     var instance = Target.apply(this, arguments); 
     for (var i = 1; i < args.length; i++) { 
      args[i].call(instance); 
     } 
     return instance; 
    }; 
    F.prototype = Target.prototype; 
    return F; 
}; 

// usage 

Rectangle = mixin(Rectangle, Sizeable, Positionnable); 

這工作一個假設下:在mixin的構造函數不要指望任何參數。如果您必須將參數傳遞給它們,則必須在目標/子構造函數中顯式調用它們。

+0

感謝您的幫助。如果沒有其他方式,我可能會這麼做,但是我看到的「問題」是我必須做兩件事而不是一件事:1)調用子構造函數中的父構造函數,2)合併原型。我想在一個函數中完成所有這些工作,但爲了做到這一點,我需要有可能訪問和分配構造函數。可能嗎 ?謝謝。 – Virus721

+0

@ Virus721:您應該始終在子構造函數中調用父構造函數,因爲這是所有實例特定的初始化發生的地方。當然,如果父構造函數不做任何事情(即它們不包含任何代碼),那麼您不必調用它們。如果您可以重新定義「矩形」功能,則可以自動完成整個過程。我會舉一個例子。 –

+0

Dojo的mixin功能讓我想起了這個問題,並自動處理構造函數鏈。根據您的需求和要求,我建議您考慮一下。 – Phix

0
if you use Object.Create(),you have to think about browser compatibility. you can write 
a function to resolve the issue.eg: 

    function multipleinheritPrototype() { 
     if (arguments.length == 0) { 
      return; 
     } 
     var args = arguments; 
     var sub = args[0]; 
     var constructor = sub.prototype.constructor; 
     if (!Object.create) { 
      Object.prototype.create = function (obj) { 

       function f() { 
       } 

       f.prototype = obj; 
       return new f(); 
      }; 
     } 
     var base; 
     for (var i = 1; i < args.length; i++) { 
      base = Object.create(args[i].prototype); 
      for (var attr in base) { 
       sub.prototype[attr] = base[attr]; 
      } 
     } 
     sub.prototype.constructor = constructor; 

    }  
    you can such so use it. 
    multipleinheritPrototype(Rectangle, Sizeable, Positionnable); 
+0

如果您僅將它用於第一個參數,那麼'Object.create'很容易變形:https://developer.mozilla.org/en-US/文檔/網絡/的JavaScript /參考/ Global_Objects /對象/創建#填充工具。順便說一句,你必須將該函數分配給Object.create而不是Object.prototype.create。 –

+0

謝謝。看起來也很有趣,我會試試看。 – Virus721