简体   繁体   English

具有多个对象的Javascript原型继承

[英]Javascript Prototypal inheritance with Multiple Objects

Say I have 5 Objects 说我有5个对象

Callback
Perishable
Object1
Object2
Object3

Object1 needs to extend the Callback but not the Perishable object, whereas Object 2 should extend both and Object 3 should extend Perishable but not callback. Object1需要扩展回调,但不扩展易腐对象,而Object 2应扩展两者,而Object 3应扩展易腐,但不扩展回调。

I know this works... 我知道这可行...

Object1.prototype = new Callback();
Object3.prototype = new Perishable();

but how would I do something like (I know this isnt working) 但是我会怎么做(我知道这是行不通的)

Object2.prototype = new Callback() && new Perishable();

You can use extend function from Underscore.js library . 您可以使用Underscore.js库中的扩展功能

The code would look like this: 代码如下所示:

_.extend(Object1.prototype, Callback.prototype);
_.extend(Object1.prototype, Perishable.prototype);

Here's JS fiddle: http://jsfiddle.net/yb7kkh4e/2/ 这是JS小提琴: http : //jsfiddle.net/yb7kkh4e/2/

If you don't want any external dependencies, you can use this implementation of extend : 如果您不需要任何外部依赖关系,则可以使用extend这种实现:

function __extends(d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    var a = function(){}; a.prototype = new b();
    for (var p in a.prototype) d.prototype[p] = a.prototype[p];   
};

Example: 例:

var animal = function(){

};

animal.prototype.run = function(){
     console.log("running");   
};

var feline = function(){

};

feline.prototype.hunt = function(){
     console.log("hunting");   
};

var cat = function(){

};

__extends(cat, animal);
__extends(cat, feline);

var scaryCat = new cat();

scaryCat.run();

scaryCat.hunt();

Fiddle: http://jsfiddle.net/apqwf93a/9/ 小提琴: http : //jsfiddle.net/apqwf93a/9/

Usually when you want to extend multiple objects you have to look if your design is correct. 通常,当您要扩展多个对象时,必须查看设计是否正确。 Is the object the other object? 该对象是另一个对象吗?

For example a Cat is an Animal and a Cat can move. 例如,猫是动物,猫可以移动。 To extend the Cat from Movable would be wrong because the Cat is not a Movable it can move so it should implement Movable or leave default implementation of Movable. 将Cat从Movable扩展将是错误的,因为Cat不是可移动的Movable,因此它应实现Movable或保留Movable的默认实现。

The example of Cat Feline and Animal is fine but could be solved without multiple inheritance. 猫猫和动物的例子很好,但无需多重继承即可解决。 A Cat is a Feline and a Feline is an Animal so no reason for Cat to both inherit from Feline and Animal you could have Cat inherit from Feline and Feline from Animal. 猫是猫科动物,猫是动物,因此猫没有理由既要从猫科动物和动物继承,也可以让猫从猫科动物继承而猫从动物继承。

The chosen answer deals with the prototype part of mix ins (implements) but doesn't cover how to initialize instance specific members. 选择的答案涉及混入(实现)的原型部分,但不涉及如何初始化实例特定的成员。 Here is the mix in part of the following answer that does: 以下是部分答案的组合:

Multiple inheritance with mix ins 混入多重继承

Some things are better not to be inherited, if a Cat can move and than a Cat should not inherit from Movable. 如果Cat可以移动并且Cat不应从Movable继承,则最好不要继承某些东西。 A Cat is not a Movable but rather a Cat can move. 猫不是可动的,而是猫可以移动。 In a class based language Cat would have to implement Movable. 在基于类的语言中,Cat必须实现Movable。 In JavaScript we can define Movable and define implementation here, Cat can either override, extend it or us it's default implementation. 在JavaScript中,我们可以在此处定义Movable并定义实现,Cat可以覆盖,扩展它,也可以将其作为默认实现。

For Movable we have instance specific members (like location ). 对于Movable,我们有特定于实例的成员(例如location )。 And we have members that are not instance specific (like the function move()). 而且,我们的成员不是特定于实例的(例如,函数move())。 Instance specific members will be set by calling mxIns (added by mixin helper function) when creating an instance. 创建实例时,将通过调用mxIns(由mixin helper函数添加)来设置实例特定的成员。 Prototype members will be copied one by one on Cat.prototype from Movable.prototype using the mixin helper function. 原型成员将使用mixin辅助函数从Movable.prototype上在Cat.prototype上一一复制。

var Mixin = function Mixin(args){
  var i, len;
  if(this.mixIns){
    i=-1;len=this.mixIns.length;
    while(++i<len){
        this.mixIns[i].call(this,args);
      }
  }  
};
Mixin.mix = function(constructor, mix){
  var thing
  ,cProto=constructor.prototype
  ,mProto=mix.prototype;
  //no extending, if multiple prototype uhs
  // have members with the same name then use
  // the last
  for(thing in mProto){
    if(Object.hasOwnProperty.call(mProto, thing)){
      cProto[thing]=mProto[thing];
    }
  }
  //instance intialisers
  cProto.mixIns = cProto.mixIns || [];
  cProto.mixIns.push(mix);
};
var Movable = function(args){
  args=args || {};
  //demo how to set defaults with truthy
  // not checking validaty
  this.location=args.location;
  this.isStuck = (args.isStuck===true);//defaults to false
  this.canMove = (args.canMove!==false);//defaults to true
  //speed defaults to 4
  this.speed = (args.speed===0)?0:(args.speed || 4);
};
Movable.prototype.move=function(){
  console.log('I am moving, default implementation.');
};
var Animal = function(args){
  args = args || {};
  this.name = args.name || "thing";
};
var Cat = function(args){
  Animal.call(args);
  //if an object can have others mixed in
  //  then this is needed to initialise 
  //  instance members
  Mixin.call(this,args);
};
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Mixin.mix(Cat,Movable);
var poochie = new Cat({
  name:"poochie",
  location: {x:0,y:22}
});
poochie.move();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM