Es6 Class Multiple Inheritance

ES6 Class Multiple inheritance

An object can only have one prototype. Inheriting from two classes can be done by creating a parent object as a combination of two parent prototypes.

The syntax for subclassing makes it possible to do that in the declaration, since the right-hand side of the extends clause can be any expression. Thus, you can write a function that combines prototypes according to whatever criteria you like, and call that function in the class declaration.

How to use one class to extend multiple classes (not multiple inheritance)?

You could use Mix-ins for this (example in MDN)

It would be something like this:

class Parent {
someParentMethod () {
console.log('Parent')
}
}

class ChildOne extends Parent {
someChildOneMethod () {
console.log('someChildOneMethod')
}
}

class ChildTwo extends Parent {
someChildTwoMethod () {
console.log('someChildTwoMethod')
}
}

// define GrandChild as a Mix-in:
let GrandChild = Base => class extends Base {
someGrandChildMethod() {
console.log('someGrandChildMethod')
}
};

//Then:
class GrandChildOne extends GrandChild(ChildOne) { }
class GrandChildTwo extends GrandChild(ChildTwo) { }

const grandChildOne = new GrandChildOne()
const grandChildTwo = new GrandChildTwo()

grandChildOne.someChildOneMethod();
grandChildTwo.someChildTwoMethod();

ES6 Class multiple inheritance through mixins

If your superclass contains a constructor, you have to call the super() method in the child's constructor:

const RaceDayService = superclass => class extends superclass {     constructor(){        super();        console.log('service');    }}
const RaceDayDB = superclass => class extends superclass { constructor(){ super(); console.log('db'); }}
class RaceDayUI { constructor(){ console.log('ui'); }}
class RaceDay extends RaceDayDB(RaceDayService(RaceDayUI)){ constructor(options){ super(); console.log('main'); }}
const raceDay = new RaceDay();

Multiple inheritance using classes

You can pick and choose which methods from other classes you want to add to an existing class as long as your new object has the instance data and methods that the methods you are adding expect to be on that object.

class Walker {
constructor() {}
walk() {
console.log("I am walking");
}
// more functions
}

class Runner {
constructor() {}
run() {
console.log("I am running");
}
// more functions
}

class Participant {
constructor() {}
}

// add methods from other classes to the Participant class
Participant.prototype.run = Runner.prototype.run;
Participant.prototype.walk = Walker.prototype.walk;

Keep in mind that methods are just functions that are properties on the prototype. So, you can assign any functions to the prototype that you want as long as the object you put them on has the right supporting instance data or other methods that those newly added methods might need.


Of course, if we understood more of your overall problem, you may also be able to solve your problem with more classical inheritance, but you can't use inheritance to solve it the exact way you asked to solve it.

Standard inheritance inherits all the methods of the base class. If you just want some of them, you will have to modify the prototype object manually to put just the methods you want there.

In the future, you will get a better set of answers if you describe the problem you're trying to solve rather than the solution you're trying to implement. That lets us understand what you're really trying to accomplish and allows us to offer solutions you haven't even thought of yet.

javaScript - multiple inheritance in ES6,

In many cases multiple inheritance in JavaScript indicates wrong design decision. It may result in hacky objects that don't behave as they should. The way it is done should always be determined by particular objects. In some cases a shallow copy of own properties is needed, in another the entire prototype chain should be traversed. Composition over inheritance is often a better choice.

The problem in the code above is that class constructors are not called. Mix has empty constructor. This is the reason why PersonWithEmitter doesn't work as expected.

Multiple constructor function calls can generally be stacked like:

function Foo(...args) {
let _this = this;
_this = Bar.apply(_this, args);
_this = Baz.apply(_this, args);
return _this;
}

This won't work if Bar or Baz is ES6 class because it contains a mechanism that prevents it from being called without new. In this case they should be instantiated:

function Foo(...args) {
copyProperties(this, new Bar(...args));
copyProperties(this, new Baz(...args));
}

Static and prototype properties may also be copied to Foo like is shown in code above.

If the case is narrowed down to Node.js EventEmitter, it can be handled like a special case. Its implementation is certain and stable. It is already known that EventEmitter does initialization in constructor, it has a shallow prototype chain and property descriptors. So it likely should be:

class Foo extends Bar {
constructor(...args) {
super(...args)
EventEmitter.call(this);
// or
// EventEmitter.init.call(this);
}
copyProperties(Foo.prototype, EventEmitter.prototype);

JavaScript efficient solution for multi-inheritance

Here is a working solution I came up with at some point and gave up because I though there might be a better solution.

@Mörre: I'm not sure this is what you advised me to do in the comments: is this what you called object composition ? Or am I going all wrong here ?

Demo: https://jsfiddle.net/Lau1989/4ba8yrc8/1/

function mix(classA, classB) {
var instanceA = new classA(),
instanceB = new classB();
for (var prop in instanceA) {
instanceB[prop] = instanceA[prop];
}
return instanceB;
}

var Bird = function() { this.className = 'Bird'; };
Bird.prototype = mix(Animal, Flying_object);
var instance = new Bird();


Related Topics



Leave a reply



Submit