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
Why JavaScript Function Declaration (And Expression)
Dynamic Extension Context Menu That Depends on Selected Text
Why Isn't [1,2,3] Equal to Itself in JavaScript
How to Import a CSS File in a React Component
Logging Clientside JavaScript Errors on Server
Getting a Jquery Selector for an Element
Solve Cross Origin Resource Sharing with Flask
How to Store a Global Value (Not Necessarily a Global Variable) in Jquery
Puppeteer - Scroll Down Until You Can't Anymore
How to Test If a Letter in a String Is Uppercase or Lowercase Using JavaScript
ASP.NET MVC 3 Razor: Include JavaScript File in the Head Tag
Angularjs Toggle Class Using Ng-Class
Access to Es6 Array Element Index Inside For-Of Loop
How to Make a JSON Call to an Url
Where Would I Use a Bitwise Operator in JavaScript