Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript diamond inheritance structure

Using node but Looking for a way around diamond inheritance in JavaScript:

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();

No problems here..but I then need to make everything that is available in Foo and Bar (and Base) in another all encompassing object:

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' gets printed twice which isn't what I was after. Doing inheritance like this probably isn't the best way so looking for alternatives / suggestions to deal with this diamond shape structure.

P.S. Haven't included the original code but modified to hopefully simplify - I've done this by hand, don't think there are any mistakes but the point I'm trying to get across should be there.

like image 572
gratz Avatar asked Oct 04 '22 03:10

gratz


2 Answers

Can you use delegation?

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();
}

You could also use mixins, but you need to add it to your class system. Ext-JS supports mixins http://www.sencha.com/learn/sencha-class-system

// My/sample/CanSing.js
Ext.define('My.sample.CanSing', {
    sing: function(songName) {
        alert("I'm singing " + songName);
    }
});

// My/sample/CanPlayGuitar.js
Ext.define('My.sample.CanPlayGuitar', {
    playGuitar: function() {
        alert("I'm playing guitar");
    }
});

// My/sample/CanComposeSongs.js
Ext.define('My.sample.CanComposeSongs', {
    composeSongs: function() {
        alert("I'm composing songs");

        return this;
    }
});

// My/sample/CoolGuy.js
Ext.define('My.sample.CoolGuy', {
    extend: 'My.sample.Person',
    mixins: {
        canSing: 'My.sample.CanSing',
        canPlayGuitar: 'My.sample.CanPlayGuitar'
    }
});

// My/sample/Musician.js
Ext.define('My.sample.Musician', {
    extend: 'My.sample.Person',
    mixins: {
        canSing: 'My.sample.CanSing',
        canPlayGuitar: 'My.sample.CanPlayGuitar',
        canComposeSongs: 'My.sample.CanComposeSongs'
    }
});

// app.js
var nicolas = new My.sample.CoolGuy("Nicolas");
nicolas.sing("November Rain"); // alerts "I'm singing November Rain"
like image 135
Juan Mendes Avatar answered Oct 10 '22 01:10

Juan Mendes


That's totally impossible; Javascript does not support multiple inheritance.

In particular, you cannot have a single object that inherits from two prototypes.

Instead, you can manually copy all of the functions from both prototypes to your prototype. (eg, using a mixin or extends method)

like image 35
SLaks Avatar answered Oct 10 '22 01:10

SLaks