Is there a way to create interfaces in ES6 / Node 4?

后端 未结 6 1691
[愿得一人]
[愿得一人] 2021-01-30 08:13

ES6 is fully available in Node 4. I was wondering whether it includes a concept of interface to define method contracts as in MyClass implements MyInterface.

6条回答
  •  青春惊慌失措
    2021-01-30 08:42

    This is my solution for the problem. You can 'implement' multiple interfaces by overriding one Interface with another.

    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'
    

    EDIT:

    I improved the code so you now can simply use implement(baseClass, interface1, interface2, ...) in the extend.

    /**
    * 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'
    

提交回复
热议问题