Multiple inheritance using classes

前端 未结 4 1311
小蘑菇
小蘑菇 2020-12-11 14:15

Is it possible to extend only some specific part from multiple classes? Example:

4条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-11 14:36

    Having a look on the provided example, I immediately would suggest "... please consider decomposition."

    For the given code it was extracting both behaviors "walk" and "run". Thus a Walker might end up as a hypothetical Person withWalkingAbility, a Runner then likewise becomes a Person withRunningAbility. All the // more functions within the originally provided Walker and Runner code then could be implemented by a Person class.

    var
      withSelfAwareWalkingAbility = (function mixinFactory () { // does create a closure ...
        function walking() {                                    //
          console.log("I'm walking");                           //
        }                                                       //
        return function abilityMixin () {                       //
          this.walk = walking; // shared code.                  // ... but shares its
        };                                                      // *ability* implementation.
      }()),
    
      withSelfAwareRunningAbility = (function mixinFactory () { // does create a closure ...
        function running() {                                    //
          console.log("I'm running");                           //
        }                                                       //
        return function abilityMixin () {                       //
          this.run = running;                                   // ... but shares its
        };                                                      // *ability* implementation.
      }());
    
    
    class Person {
      constructor() {
        // `Person` specific instance slots.
      }
      // `Person` specific prototypal methods.
    }
    

    A first big win was that one now is in control of where to place the composition, either at prototype level or within the constructor. It depends on a Walker's / Runner's final design and can be answered best by the OP her/himself.

    class Walker extends Person {
      constructor() {
        super();
        withSelfAwareWalkingAbility.call(this); // composition at object level / instantiation time.
      }
    }
    

    ... versus ...

    class Runner extends Person {
      constructor() {
        super();
      }
    }
    withSelfAwareRunningAbility.call(Runner.prototype); // composition at a `Runner`'s `prototype` slot.
    

    var
      withSelfAwareWalkingAbility = (function mixinFactory () {
        function walking() {
          console.log("I'm walking");
        }
        return function abilityMixin () {
          this.walk = walking;
        };
      }()),
    
      withSelfAwareRunningAbility = (function mixinFactory () {
        function running() {
          console.log("I'm running");
        }
        return function abilityMixin () {
          this.run = running;
        };
      }());
    
    
    class Person {
      constructor() {
        // `Person` specific instance slots.
      }
      // `Person` specific prototypal methods.
    }
    
    
    class Walker extends Person {
      constructor() {
        super();
        withSelfAwareWalkingAbility.call(this);
      }
    }
    
    class Runner extends Person {
      constructor() {
        super();
      }
    }
    withSelfAwareRunningAbility.call(Runner.prototype);
    
    
    var
      walker = (new Walker),
      runner = (new Runner);
    
    console.log('walker : ', walker); // Walker {walk: function}
    console.log('(walker instanceof Walker) ? ', (walker instanceof Walker)); // true
    console.log('(walker instanceof Person) ? ', (walker instanceof Person)); // true
    console.log('(walker instanceof Runner) ? ', (walker instanceof Runner)); // false
    walker.walk(); //  "I'm walking"
    console.log('(walker.hasOwnProperty("walk")) ? ', walker.hasOwnProperty("walk")); // true
    
    console.log('\n');
    
    console.log('runner : ', runner); // Runner {}
    console.log('(runner instanceof Runner) ? ', (runner instanceof Runner)); // true
    console.log('(runner instanceof Person) ? ', (runner instanceof Person)); // true
    console.log('(runner instanceof Walker) ? ', (runner instanceof Walker)); // false
    runner.run(); //  "I'm running"
    console.log('(runner.hasOwnProperty("run")) ? ', runner.hasOwnProperty("run")); // false
    .as-console-wrapper { max-height: 100%!important; top: 0; }

    Another win of decomposing behavior into smaller or even atomic "composable units of reuse"[^1] comes from the easiness of composing them again into bigger tailored mixins/traits like ...

    function withSelfAwareWalkingAndRunningAbility() {
      withSelfAwareWalkingAbility.call(this);
      withSelfAwareRunningAbility.call(this);
    }
    

    [^1]: SCG, University of Bern: »Talents: Dynamically Composable Units of Reuse«

    Note ... there is now a second part of this answer providing the example from above again, but with a real trait approach backed by a library

提交回复
热议问题