Bad:
Good:
constructor(age) {
this.age = age;
}
move() { /* ... */ }
}
class Mammal extends Animal {
constructor(age, furColor) {
super(age);
this.furColor = furColor;
}
liveBirth() { /* ... */ }
}
class Human extends Mammal {
constructor(age, furColor, languageSpoken) {
super(age, furColor);
this.languageSpoken = languageSpoken;
}
speak() { /* ... */ }
}
Bad:
Good:
this.make = make;
this.model = model;
this.color = color;
}
setMake(make) {
this.make = make;
// NOTE: Returning this for chaining
return this;
}
setModel(model) {
this.model = model;
// NOTE: Returning this for chaining
return this;
}
setColor(color) {
this.color = color;
// NOTE: Returning this for chaining
return this;
}
save() {
console.log(this.make, this.model, this.color);
// NOTE: Returning this for chaining
}
const car = new Car('Ford','F-150','red')
.setColor('pink')
.save();
You might be wondering then, “when should I use inheritance?” It
depends on your problem at hand, but this is a decent list of when inheritance
makes more sense than composition:
- Your inheritance represents an “is-a” relationship and not a “has-a”
relationship (Human->Animal vs. User->UserDetails). - You can reuse code from the base classes (Humans can move like all animals).
- You want to make global changes to derived classes by changing a base class.
(Change the caloric expenditure of all animals when they move).
Bad:
class EmployeeTaxData {
constructor(ssn, salary) {
this.ssn = ssn;
this.salary = salary;
}
// ...
}
class Employee {
constructor(name, email) {
this.name = name;
this.email = email;
}
setTaxData(ssn, salary) {
this.taxData = new EmployeeTaxData(ssn, salary);
}
// ...
}