Javascript菱形继承结构

Javascript菱形继承结构,javascript,inheritance,Javascript,Inheritance,在JavaScript中使用node但寻找绕过菱形继承的方法: var util = require('util'); function Base(example_value) { console.log(example_value); this.example_property = example_value; this.example_method = function() { ... }; } function Foo(settings) { var f = setti

在JavaScript中使用node但寻找绕过菱形继承的方法:

var util = require('util');

function Base(example_value) {
  console.log(example_value);
  this.example_property = example_value;
  this.example_method = function() { ... };
}

function Foo(settings) {
  var f = settings.f;
  Base.call(x);
  this.settings = settings;
}

util.inherits(Foo, Base);

function Bar(settings) {
  var b = settings.b;
  Base.call(b);
  this.settings = settings;
}

util.inherits(Bar, Base);

var foo = new Foo({f: 'bar'});
// 'bar' gets printed and I can call methods from Base..
foo.example_method();
var bar = new Bar({b: 'foo'});
// 'foo' gets printed and I can call methods from Base..
bar.example_method();
这里没有问题。但是我需要在另一个包罗万象的对象中创建Foo和Bar(以及Base)中可用的所有内容:

function Top(settings) {
  Foo.call(this, settings);
  Bar.call(this, settings);
}

util.inherits(Top, Foo);
util.inhertis(Top, Bar);

var top = new Top({some: 'value'});
“value”被打印了两次,这不是我想要的。像这样继承可能不是最好的方式,因此寻找替代方案/建议来处理这种菱形结构


附言中没有包含原始代码,但进行了修改,希望能够简化-我是手工完成的,不认为有任何错误,但我试图表达的观点应该在那里。

这是完全不可能的;Javascript不支持多重继承

特别是,不能有一个从两个原型继承的对象


相反,您可以手动将两个原型中的所有函数复制到您的原型中。(例如,使用mixin或extends方法)

我不知道您对经典继承有多着迷,但避免多重继承(以及菱形继承问题)的一种方法是使用mixin(mixin)。用外行的话说:你在基类上添加了更多的东西,直到它完成你想要的一切。

你能使用委托吗

function Top(settings) {
  this.foo = new Foo(settings);
  this.bar = new Bar(settings);
}

Top.prototype.conflictingMethod = function() {
   // use either this.foo or this.bar
}
Top.prototype.anotherMethod = function() {
   return this.foo.anotherMethod();
}
也可以使用mixin,但需要将其添加到类系统中。extjs支持mixin


谢谢你所有有效的答案,我会投票的。我总结了一个更有用、更真实的例子,它似乎可以完成这项工作,所以我在这里提供了一个答案,但似乎有很多方法可以做到这一点:

function TXObject(settings) {
  this.transmit = function(data) {
    // Transmit data using settings
    console.log('Transmitting data: ' + data);
  }
}

function RXObject(settings) {
  this.receive = function(data) {
    // Receive data using settings
    console.log('Receiving data: ' + data);
  }
}



function Device(settings) {
  this.settings = settings;
}

Device.prototype.asTransmitter = function() {
  var txInstance = new TXObject(this.settings);
  this.transmit = txInstance.transmit.bind(txInstance);
  // Alternatively to wrap txInstance.transmit and add functionality..
  // this.transmit = function() { txInstance.transmit(...); }
  return this;
}

Device.prototype.asReceiver = function() {
  var rxInstance = new RXObject(this.settings);
  this.receive = rxInstance.receive.bind(rxInstance);
  // Same thing for receive..
  // this.receive = function() { rxInstance.receive(...); }
  return this;
}

Device.prototype.asTransceiver = function() {
  this.asTransmitter();
  this.asReceiver();
  return this;
}

var d = new Device({foo: 'bar'});
console.log(d);
var tx = new Device({foo: 'bar'}).asTransmitter();
console.log(tx);
var rx = new Device({foo: 'bar'}).asReceiver();
console.log(rx);
var txrx = new Device({foo: 'bar'}).asTransceiver();
console.log(txrx);

tx.transmit('hello');
rx.receive('world');

txrx.transmit('hello');
txrx.receive('world');

再次感谢

我根本看不出“value”是如何打印的,因为“settings”对象既没有“f”属性,也没有“b”属性。@Pointy:
f
b
是在构造函数参数中设置的(例如
var foo=new foo({f:'bar');
)。@Cory yes,函数“Top”是用一个名为“some”的对象调用的。“Top”函数传递给对象,它同时传递给“Foo”和“Bar”。@Pointy:好的,我明白了。假设“'value'被打印两次”,我假设示例代码是错误的。谢谢你来接这个例子?否则,这应该是一个评论。没有例子,互联网上充满了混合的例子。我坚信这不应该是一个评论,因为这是一个答案。它回答了一个问题:如何避免菱形继承问题?当多个mixin之间存在冲突时该怎么办?您应该解释mixin如何避免这种情况,这是依赖于mixin实现的多重继承的主要问题。你可以抛出一个错误,选择最后一个实现,保留第一个实现,进入一个while(true)循环,永不退出,接管世界,奴役人类以获取生物量mixin通过不需要构造函数来解决菱形继承问题,冲突解决超出了我的回答范围。我不相信一个完整的教科书回复是有道理的,欢迎你提供你自己的。感谢你的两个回复,我一直在研究如何扩展或混合我需要在这里实现的内容,并想出了各种方法来实现。这里有一个我想到的:评论和意见非常受欢迎OP并不需要它来继承两个原型,可以使用混音,不是吗?@JuanMendes:是的;我想提一下。
function TXObject(settings) {
  this.transmit = function(data) {
    // Transmit data using settings
    console.log('Transmitting data: ' + data);
  }
}

function RXObject(settings) {
  this.receive = function(data) {
    // Receive data using settings
    console.log('Receiving data: ' + data);
  }
}



function Device(settings) {
  this.settings = settings;
}

Device.prototype.asTransmitter = function() {
  var txInstance = new TXObject(this.settings);
  this.transmit = txInstance.transmit.bind(txInstance);
  // Alternatively to wrap txInstance.transmit and add functionality..
  // this.transmit = function() { txInstance.transmit(...); }
  return this;
}

Device.prototype.asReceiver = function() {
  var rxInstance = new RXObject(this.settings);
  this.receive = rxInstance.receive.bind(rxInstance);
  // Same thing for receive..
  // this.receive = function() { rxInstance.receive(...); }
  return this;
}

Device.prototype.asTransceiver = function() {
  this.asTransmitter();
  this.asReceiver();
  return this;
}

var d = new Device({foo: 'bar'});
console.log(d);
var tx = new Device({foo: 'bar'}).asTransmitter();
console.log(tx);
var rx = new Device({foo: 'bar'}).asReceiver();
console.log(rx);
var txrx = new Device({foo: 'bar'}).asTransceiver();
console.log(txrx);

tx.transmit('hello');
rx.receive('world');

txrx.transmit('hello');
txrx.receive('world');