Passing functions from class to class

Viewed 41

I want to inherit all the methods from source classes into my main target class/function. I kind of did something, but I wonder if there are better or gentler ways to do this.
The idea is that I can keep good readability and separate methods in groups (files) so I know what belongs where.
P.S. Sorry for my bad english

Here's how I did it:

    function Main(){
      const self = this
      self.name = 'Main' 
      self.speak = () => {
        console.log(`called in class Main by class ${this.name}`)
      }
    }

    class A{
      //fake variables for IDE autofill
      //no constructor needed
      speakA(){
        console.log(`called in class A by class ${this.name}`)
      }
    }
    class B{
      speakB(){
        console.log(`called in class B by class ${this.name}`)
      }
    }
    class C{
      speakC(){
        console.log(`called in class C by class ${this.name}`)
      }
    }


    ;(function assignOFunctionsToObject(target, ...sources){
        sources.forEach(source => {
            Object.getOwnPropertyNames(source.prototype).forEach(name => {
                if(typeof source.prototype[name] === "function") {
                  target.prototype[name] = source.prototype[name]
                }
            })
        })
    })(Main,
        A, B, C)
        
    let main = new Main()
    main.speak()
    main.speakA()
    main.speakB()
    main.speakC()

2 Answers

Implementing utility functions within and across different modules one could at least choose 3 different approaches ...

  1. Write a function based mixin which is a single function with (this aware) methods bound to the function's this context.

    • apply the imported mixin to whichever object is in need of the mixin's methods.
  2. Write an object based mixin which is a single object with (this aware) methods.

    • assign the imported mixin to whichever object is in need of the mixin's methods.
  3. Write and export (this aware) functions.

    • make the imported functions part of an ad-hoc created object and assign the latter to whichever object is in need of the just created mixin's methods.

// module ... function_based_utility_methods_mixin_A.js
//
function speakA() {
  console.log(`called as 'speakA' by instance of type '${ this.type }'`);
}
function speakAA() {
  console.log(`called as 'speakAA' by instance of type '${ this.type }'`);
}

/* export default */function withUtilityMethods_A() {
  this.speakA = speakA;
  this.speakAA = speakAA;
}


// module ... object_based_utility_methods_mixin_B.js
//
function speakB() {
  console.log(`called as 'speakB' by instance of type '${ this.type }'`);
}
function speakBB() {
  console.log(`called as 'speakBB' by instance of type '${ this.type }'`);
}

/* export default */const utilityMethods_B = {
  speakB,
  speakBB,
}


// module ... utility_methods_C.js
//
/* export */function speakC() {
  console.log(`called as 'speakC' by instance of type '${ this.type }'`);
}
/* export */function speakCC() {
  console.log(`called as 'speakCC' by instance of type '${ this.type }'`);
}


// module ... main.js

// import withUtilityMethods_A from 'function_based_utility_methods_mixin_A.js';
// import utilityMethods_B from 'object_based_utility_methods_mixin_B.js';
// import { speakC, speakCC } from 'utility_methods_C.js';

function Main () {
  this.type = 'main';
  this.speak = () => {
    console.log(`called as 'speak' by instance of type '${ this.type }'`);
  };
}

// option 1 ... 
// - APPLY a function based mixin to the
//   `Main` constructor function's prototype.
withUtilityMethods_A.call(Main.prototype);

// option 2 ... 
// - ASSIGN an object based mixin to the
//   `Main` constructor function's prototype.
Object.assign(Main.prototype, utilityMethods_B);

// option 3 ... 
// - ASSIGN an ad-hoc created object based mixin
//   to the `Main` constructor function's prototype.
Object.assign(Main.prototype, { speakC, speakCC });

const main = new Main();
main.speak();

main.speakA();
main.speakAA();

main.speakB();
main.speakBB();

main.speakC();
main.speakCC();

console.log({
  mainPrototype: Main.prototype
});
.as-console-wrapper { min-height: 100%!important; top: 0; }

Related