OO and Inheritance
Inheritance is an intuitive concept to understand, and a representative idea taught for object oriented programming. It has been obsolesced since being called out as less favorable than composition by the Gang of Four’s 1994 book Design Patterns: Elements of Reusable Object-Oriented Software.
Inheritance is idea of thinking about lower level abstractions (motorcycle, car, truck) as inheriting properties of higher level abstractions (vehicle). Composition is the idea lower level abstractions (wheels, engine, wings, etc) compose the characteristics higher level abstractions (vehicle).
Below is a JavaScript example of composition.
The abstraction will be that a character is composed of an armor and weapon.
Three types of armor: heavy, medium, light.
const heavyArmor = (character) => ({
damage: (amount) => {
character.health = character.health - 3;
console.log(`${amount} damage reduced health to ${character.health}!`);
}
})const mediumArmor = (character) => ({
damage: (amount) => {
character.health = character.health - 2;
console.log(`${amount} damage reduced health to ${character.health}!`);
}
})const lightArmor = (character) => ({
damage: (amount) => {
character.health = character.health - 1;
console.log(`${amount} damage reduced health to ${character.health}!`);
}
})
Three types of weapons: sword, axe, hammer.
const sword = (character) => ({
attack: (enemy) => {
enemy.damage(10)
}
})const axe = (character) => ({
attack: (enemy) => {
enemy.damage(11)
}
})const hammer = (character) => ({
attack: (enemy) => {
enemy.damage(12)
}
})
Three species, each defined by their composition of weapon and armor
const human = () => {
let character = {
health: 100
}
return Object.assign(character, mediumArmor(character), sword());
}const orc = () => {
let character = {
health: 100
}
return Object.assign(character, heavyArmor(character), axe());
}const elf = () => {
let character = {
health: 100
}
return Object.assign(character, lightArmor(character), hammer());
}
A factory function that returns the object appropriate for the species
const createCharacter = function(species){
if (species === 'human') return human();
if (species === 'orc') return orc();
if (species === 'elf') return elf();
}
Now I have a character creator, that I can use to create character that can attack and mitigate damage.
let me = createCharacter('human');
let them = createCharacter('orc');
me.attack(them);
them.attack(me);
Pattern: Factory
Refactoring: Replace Conditional with Polymorphism
Principle: Dependency Inversion