Search code examples
javascriptoopcompositiones6-class

How do I use composition with es6 classes in the same way as this example does using factory functions?


(please note this is not a duplicate question, see @Jeff M's answer below)

I am trying to understand es6 class syntax. I want to compose my classes in the same way as this code does using factory functions:

Example 1:

const barker = (state) => ({
  bark: () => console.log("Woof, I am " + state.name)
});

const driver = (state) => ({
  drive: () => state.position = state.position + state.speed
});

const murderRobotDog = (name) => {
  let state = {
    name,
    speed: 100,
    position: 0
  };
  return Object.assign({},
    barker(state),
    driver(state)
  );
};

const bruno = murderRobotDog("bruno");
bruno.bark(); // "Woof, I am Bruno"

My working example of class composition using 'class' from a completely different tutorial looks like this:

Example 2:

class Employee {
  constructor(firstName, familyName) {
  this._firstName = firstName;
  this._familyName = familyName;
  }

  getFullName() {
  return `${this._firstName} ${this._familyName}`;
  }
}

class Group {
  constructor(manager /* : Employee */ ) {
    this._manager = manager;
    this._managedEmployees = [];
  }

  addEmployee(employee) {
    this._managedEmployees.push(employee);
  }
}

I can see how the concept of composition works, but these seem like very different ways of doing it. The first example using the factories seems the most intuitive, but I want to use the es6 class syntax (don't worry why :)

Maybe I am missing something and the answer is obvious, but how would I do exactly what is done in example 1 using es6 classes in the most simplistic way? THANKS.


Solution

  • I can see you're using MPJ's "composition" example, so the first thing you need to know is that MPJ got composition completely wrong. What MPJ actually demonstrated (without him realizing) was multiple inheritance. That's why someone already flagged your question as a possible duplicate of another multiple inheritance question.

    JavaScript's prototype chain supports only single inheritance, and since ES6 classes use the prototype chain, they too support only single inheritance. But with a little trick, we can nonetheless achieve the same effect as multiple inheritance.

    It would go like this:

    const barker = Sup => class extends Sup {
      bark() { console.log("Woof, I am " + this.name) }
    }
    
    const driver = Sup => class extends Sup {
      drive() { this.position = this.position + this.speed }
    };
    
    class murderRobotDog extends driver(barker(Object)) {
      constructor(name) {
          super();
          this.name = name;
          this.speed = 100;
          this.position = 0;
      }
    };
    
    const bruno = new murderRobotDog("bruno");
    bruno.bark(); // "Woof, I am Bruno"