JavaScript的 - 特别多继承

问题描述:

说我有以下对象类型: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),回路我会简单地合并每个基类的原型到子类的原型。这不会创建一个链(这是我想如上所述)

但是这会导致另一个问题:因为我没有使用新的基础构造函数不会被调用。所以我想知道,有没有办法也可以合并构造函数?例如,如果我可以访问和引用基础构造函数,我可以将这些基础构造函数存储在一个数组中,并为子类型构造函数分配一个函数来调用每个构造函数。

我怎么能这样做与构造函数?或者,也许有另一种方式?

感谢您的帮助!

由于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

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