Home > Back-end >  Passing functions from class to class ... How to maintain utility functionality and mixing it into o
Passing functions from class to class ... How to maintain utility functionality and mixing it into o

Time:09-27

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()

CodePudding user response:

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

CodePudding user response:

firstly is thinking about OOP, it's not good idea, add function inside existing object as it is in your example.

But if you want to add dynamically behavior to an existing object, you should use one of those patterns:

https://refactoring.guru/design-patterns/proxy

https://refactoring.guru/uk/design-patterns/visitor

  • Related