Это мое решение проблемы. Вы можете «реализовать» несколько интерфейсов, заменив один интерфейс другим.
class MyInterface {
// Declare your JS doc in the Interface to make it acceable while writing the Class and for later inheritance
/**
* Gives the sum of the given Numbers
* @param {Number} a The first Number
* @param {Number} b The second Number
* @return {Number} The sum of the Numbers
*/
sum(a, b) { this._WARNING('sum(a, b)'); }
// delcare a warning generator to notice if a method of the interface is not overridden
// Needs the function name of the Interface method or any String that gives you a hint ;)
_WARNING(fName='unknown method') {
console.warn('WARNING! Function "'+fName+'" is not overridden in '+this.constructor.name);
}
}
class MultipleInterfaces extends MyInterface {
// this is used for "implement" multiple Interfaces at once
/**
* Gives the square of the given Number
* @param {Number} a The Number
* @return {Number} The square of the Numbers
*/
square(a) { this._WARNING('square(a)'); }
}
class MyCorrectUsedClass extends MyInterface {
// You can easy use the JS doc declared in the interface
/** @inheritdoc */
sum(a, b) {
return a+b;
}
}
class MyIncorrectUsedClass extends MyInterface {
// not overriding the method sum(a, b)
}
class MyMultipleInterfacesClass extends MultipleInterfaces {
// nothing overriden to show, that it still works
}
let working = new MyCorrectUsedClass();
let notWorking = new MyIncorrectUsedClass();
let multipleInterfacesInstance = new MyMultipleInterfacesClass();
// TEST IT
console.log('working.sum(1, 2) =', working.sum(1, 2));
// output: 'working.sum(1, 2) = 3'
console.log('notWorking.sum(1, 2) =', notWorking.sum(1, 2));
// output: 'notWorking.sum(1, 2) = undefined'
// but also sends a warn to the console with 'WARNING! Function "sum(a, b)" is not overridden in MyIncorrectUsedClass'
console.log('multipleInterfacesInstance.sum(1, 2) =', multipleInterfacesInstance.sum(1, 2));
// output: 'multipleInterfacesInstance.sum(1, 2) = undefined'
// console warn: 'WARNING! Function "sum(a, b)" is not overridden in MyMultipleInterfacesClass'
console.log('multipleInterfacesInstance.square(2) =', multipleInterfacesInstance.square(2));
// output: 'multipleInterfacesInstance.square(2) = undefined'
// console warn: 'WARNING! Function "square(a)" is not overridden in MyMultipleInterfacesClass'
РЕДАКТИРОВАТЬ:
Я улучшил код, так что теперь вы можете просто использовать реализацию (baseClass, interface1, interface2, ...) в расширении.
/**
* Implements any number of interfaces to a given class.
* @param cls The class you want to use
* @param interfaces Any amount of interfaces separated by comma
* @return The class cls exteded with all methods of all implemented interfaces
*/
function implement(cls, ...interfaces) {
let clsPrototype = Object.getPrototypeOf(cls).prototype;
for (let i = 0; i < interfaces.length; i++) {
let proto = interfaces[i].prototype;
for (let methodName of Object.getOwnPropertyNames(proto)) {
if (methodName!== 'constructor')
if (typeof proto[methodName] === 'function')
if (!clsPrototype[methodName]) {
console.warn('WARNING! "'+methodName+'" of Interface "'+interfaces[i].name+'" is not declared in class "'+cls.name+'"');
clsPrototype[methodName] = proto[methodName];
}
}
}
return cls;
}
// Basic Interface to warn, whenever an not overridden method is used
class MyBaseInterface {
// declare a warning generator to notice if a method of the interface is not overridden
// Needs the function name of the Interface method or any String that gives you a hint ;)
_WARNING(fName='unknown method') {
console.warn('WARNING! Function "'+fName+'" is not overridden in '+this.constructor.name);
}
}
// create a custom class
/* This is the simplest example but you could also use
*
* class MyCustomClass1 extends implement(MyBaseInterface) {
* foo() {return 66;}
* }
*
*/
class MyCustomClass1 extends MyBaseInterface {
foo() {return 66;}
}
// create a custom interface
class MyCustomInterface1 {
// Declare your JS doc in the Interface to make it acceable while writing the Class and for later inheritance
/**
* Gives the sum of the given Numbers
* @param {Number} a The first Number
* @param {Number} b The second Number
* @return {Number} The sum of the Numbers
*/
sum(a, b) { this._WARNING('sum(a, b)'); }
}
// and another custom interface
class MyCustomInterface2 {
/**
* Gives the square of the given Number
* @param {Number} a The Number
* @return {Number} The square of the Numbers
*/
square(a) { this._WARNING('square(a)'); }
}
// Extend your custom class even more and implement the custom interfaces
class AllInterfacesImplemented extends implement(MyCustomClass1, MyCustomInterface1, MyCustomInterface2) {
/**
* @inheritdoc
*/
sum(a, b) { return a+b; }
/**
* Multiplies two Numbers
* @param {Number} a The first Number
* @param {Number} b The second Number
* @return {Number}
*/
multiply(a, b) {return a*b;}
}
// TEST IT
let x = new AllInterfacesImplemented();
console.log("x.foo() =", x.foo());
//output: 'x.foo() = 66'
console.log("x.square(2) =", x.square(2));
// output: 'x.square(2) = undefined
// console warn: 'WARNING! Function "square(a)" is not overridden in AllInterfacesImplemented'
console.log("x.sum(1, 2) =", x.sum(1, 2));
// output: 'x.sum(1, 2) = 3'
console.log("x.multiply(4, 5) =", x.multiply(4, 5));
// output: 'x.multiply(4, 5) = 20'