0

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

Sumomo
  • 563
  • 1
  • 3
  • 15
  • Possible duplicate of [ES6 Class Multiple inheritance](https://stackoverflow.com/questions/29879267/es6-class-multiple-inheritance) – lilezek Oct 17 '17 at 15:06

1 Answers1

3

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"
Jeff M
  • 2,283
  • 2
  • 20
  • 38
  • 1
    OMG Thank you!! I have been puzzling over this for weeks, I can hardly believe my hero MPJ is wrong, my world is blown apart! I read the link to the forum, but all the examples are no longer in JS. Could you help me one more time and show me how to do the MPJ example using PROPER composition in es6 classes? – Sumomo Oct 18 '17 at 08:48
  • Composition is using instance variables that are references to other objects. Like this https://pastebin.com/Edqg9ZvX – Jeff M Oct 18 '17 at 21:11
  • @JeffM MPJ didn't get composition wrong. He simply used object concatenation (or multiple inheritance as you have put it), to create a composite object as ONE of the ways to do composition. Eric Elliot has described it pretty well in his article (https://medium.com/javascript-scene/introducing-the-stamp-specification-77f8911c2fee). – Timur Mamedov May 22 '19 at 00:49
  • 1
    @TimurMamedov If it's multiple inheritance, then it's *NOT* composition. Eric Elliott is the original source of this misinformation. MPJ learned it from him, then regurgitated that same wrong information. – Jeff M May 23 '19 at 02:05
  • @JeffM Thanks for the insight, didn't know that. – Timur Mamedov May 23 '19 at 17:25