65.9K
CodeProject 正在变化。 阅读更多。
Home

JavaScript ES6 多重继承类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.23/5 (7投票s)

2017年5月28日

CPOL
viewsIcon

32095

为 ES6 添加了类多重继承的功能。

引言

我决定开始学习 JavaScript ES6 的新特性。我喜欢所有东西,除了类缺乏多重继承的支持。为了实现多重继承而不得不围绕单个类进行链式调用,这实在太麻烦了。因此,为了解决这个问题,我设计了下面的类。

多重继承类

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

它是如何工作的?

为了使多重继承起作用,我结合使用了许多新的 ES6 特性和 ES5。该类通过使用以下代码进行扩展。

// Single Inherit
class person extends ages

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

我们不是将一个类传递给 extend,而是传递一个名为 inherit 的静态函数,该函数在合并其他命名类的属性和方法后返回一个类。在 inherit 方法内部,我们接收一个包含所有要继承的类名的剩余参数。

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

这是创建每个类的实例并将其属性复制到构造函数方法中的关键特性。我们将参数从 super() 转发到构造函数。

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

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

下面是一个多重继承的完整工作示例。

完整示例代码

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

历史

版本 0.1 - 脚本的首次发布,需要完善。

© . All rights reserved.