Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / ES6

JavaScript ES6 Multiple Inheritance Class

4.23/5 (7 votes)
28 May 2017CPOL 31.8K  
Adds functionality to ES6 for multi inheritance of classes.

Introduction

I decided to jump into JavaScript ES6 and start learning the new features. I like everything except the lack of multiple inheritance support for classes. Having to chain around single classes to make multi inheritance is a pain in the ass. So in an attempt to resolve the problem, I came up with the class below.

Multi Inheritance Class

JavaScript
// Class for creating multi inheritance.
class multi
{
	// Inherit method to create base classes.
	static inherit(..._bases)
	{
		class classes {

			// The base classes
  			get base() { return _bases; }

			constructor(..._args)
			{
				var index = 0;

				for (let b of this.base) 
				{
					let obj = new b(_args[index++]);
   					multi.copy(this, obj);
				}
			}
		
		}

		// Copy over properties and methods
		for (let base of _bases) 
		{
   			multi.copy(classes, base);
   			multi.copy(classes.prototype, base.prototype);
		}

		return classes;
	}

	// Copies the properties from one class to another
	static copy(_target, _source) 
	{
    		for (let key of Reflect.ownKeys(_source)) 
			{
        		if (key !== "constructor" && key !== "prototype" && key !== "name") 
				{
	        	    let desc = Object.getOwnPropertyDescriptor(_source, key);
	        	    Object.defineProperty(_target, key, desc);
        		}
    		}
	}
}

How Does it Work?

In order for multi inheritance to work, I utilized a lot of the new ES6 features in combination with ES5. The class is extended by using the following code.

JavaScript
// Single Inherit
class person extends ages

// Multi Inherit
class person extends multi.inherit(ages, genders)

Instead of passing a class to the extend, we pass a static function called inherit, which returns a class after merging properties and methods together of other named classes. Inside the inherit method, we receive a rest parameter with all class names to inherit from.

JavaScript
// The base classes
get base() { return _bases; }

This is a key feature for creating the instances of each class and copying their properties in the constructor method. We forward the parameters from the super() to the constructor.

JavaScript
constructor(..._args)
{
	var index = 0;

	for (let b of this.base) 
	{
		let obj = new b(_args[index++]);
		multi.copy(this, obj);
	}
}

Below is a full working example of multiple inheritance.

Full Sample Code

JavaScript
// Class for creating multi inheritance.
class multi
{
	// Inherit method to create base classes.
	static inherit(..._bases)
	{
		class classes {

			// The base classes
  			get base() { return _bases; }

			constructor(..._args)
			{
				var index = 0;

				for (let b of this.base) 
				{
					let obj = new b(_args[index++]);
   					multi.copy(this, obj);
				}
			}
		
		}

		// Copy over properties and methods
		for (let base of _bases) 
		{
   			multi.copy(classes, base);
   			multi.copy(classes.prototype, base.prototype);
		}

		return classes;
	}

	// Copies the properties from one class to another
	static copy(_target, _source) 
	{
    		for (let key of Reflect.ownKeys(_source)) 
			{
        		if (key !== "constructor" && key !== "prototype" && key !== "name") 
				{
	        	    let desc = Object.getOwnPropertyDescriptor(_source, key);
	        	    Object.defineProperty(_target, key, desc);
        		}
    		}
	}
}

class ages
{
	constructor(_age) {	this.age = _age; }
	set age(_a) { this._age = _a; }
	get age() { return this._age; }
	increase() { this.age++; }
}

class genders
{
	constructor(_gender) { this.gender = _gender; }
	set gender(_g) { this._gender = _g; }
	get gender() { return this._gender; }
	male() { this._gender = 'M'; }
	female() { this._gender = 'F'; }
}

class person extends multi.inherit(ages, genders)
{
	constructor(...args)
	{
		super(18, 'M');
		this.name = args[0];
	}

	set name(_n) { this._name = _n; }
	get name() { return this._name; }
}

var p = new person('Adam');
console.log(p.name, p.age, p.gender);

History

Version 0.1 - First release of script, needs perfecting.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)