2 clarification
source | link

I reckon it would be cool that both troll and werewolf inherited its attributes from enemy and overwrote some of them.

Unfortunately this approach to polymorphism, popular in the 90s, has shown itself to be a bad idea in practice. Imagine you add 'wolf' to the enemy list - well, it shares some attributes with werewolf, so you'd want to consolidate those into a shared base class, eg. 'WolfLike'. Now you add 'Human' to the enemy list, but werewolves are sometimes humans, so they share attributes too, such as walking on 2 legs, being able to talk, etc. Do you create a 'Humanoid' common base for humans and werewolves, and do you then have to stop werewolves deriving from WolfLike? Or do you multiply inherit from both - in which case, which attribute takes precedence when something in Humanoid clashes with something in WolfLike?

The problem is that trying and model the real world as a tree of classes is ineffective. Take any 3 things and you can probably find 4 different ways to factor their behaviour into shared and non-shared. This is why many have turned to a modular or component-based model instead, where an object is comprised of several smaller objects that make up the whole, and the smaller objects can be swapped or change to make up the behaviour you want. Here you might have just 1 Enemy class, and it contains sub-objects or components for how it walks (eg. Bipedal vs. Quadrupedal), its methods of attack (eg. bite, claw, weapon, fist), its skin (green for trolls, furry for werewolves and wolves), etc.

This is still completely object-oriented, but the notion of what is a useful object is different from what used to be commonly taught in the text books. Rather than having a large inheritance tree of various abstract classes and several concrete classes at the tips of the tree, you typically have just 1 concrete class representing an abstract concept (eg. 'enemy') but which contain more concrete classes representing more abstract concepts (eg. attacks, skin type). Sometimes these second classes can be best implemented via 1 level of inheritance (eg. a base Attack class and several derived classes for specific attacks) but the deep inheritance tree is gone.

But maybe classes are too heavy to be practical, I don't know...

In most modern languages, classes aren't 'heavy'. They're just another way of writing code, and they usually just wrap the procedural approach you would have written anyway, except with easier syntax. But by all means, don't write a class where a function will do. Classes are not intrinsically better, only where they make the code easier to manage or to understand.

I reckon it would be cool that both troll and werewolf inherited its attributes from enemy and overwrote some of them.

Unfortunately this approach to polymorphism, popular in the 90s, has shown itself to be a bad idea in practice. Imagine you add 'wolf' to the enemy list - well, it shares some attributes with werewolf, so you'd want to consolidate those into a shared base class, eg. 'WolfLike'. Now you add 'Human' to the enemy list, but werewolves are sometimes humans, so they share attributes too, such as walking on 2 legs, being able to talk, etc. Do you create a 'Humanoid' common base for humans and werewolves, and do you then have to stop werewolves deriving from WolfLike? Or do you multiply inherit from both - in which case, which attribute takes precedence when something in Humanoid clashes with something in WolfLike?

The problem is that trying and model the real world as a tree is ineffective. Take any 3 things and you can probably find 4 different ways to factor their behaviour into shared and non-shared. This is why many have turned to a modular or component-based model instead, where an object is comprised of several smaller objects that make up the whole, and the smaller objects can be swapped or change to make up the behaviour you want. Here you might have just 1 Enemy class, and it contains sub-objects or components for how it walks (eg. Bipedal vs. Quadrupedal), its methods of attack (eg. bite, claw, weapon, fist), its skin (green for trolls, furry for werewolves and wolves), etc.

This is still completely object-oriented, but the notion of what is a useful object is different from what used to be commonly taught in the text books. Rather than having a large inheritance tree of various abstract classes and several concrete classes at the tips of the tree, you typically have just 1 concrete class representing an abstract concept (eg. 'enemy') but which contain more concrete classes representing more abstract concepts (eg. attacks, skin type). Sometimes these second classes can be best implemented via 1 level of inheritance (eg. a base Attack class and several derived classes for specific attacks) but the deep inheritance tree is gone.

But maybe classes are too heavy to be practical, I don't know...

In most modern languages, classes aren't 'heavy'. They're just another way of writing code, and they usually just wrap the procedural approach you would have written anyway, except with easier syntax. But by all means, don't write a class where a function will do. Classes are not intrinsically better, only where they make the code easier to manage or to understand.

I reckon it would be cool that both troll and werewolf inherited its attributes from enemy and overwrote some of them.

Unfortunately this approach to polymorphism, popular in the 90s, has shown itself to be a bad idea in practice. Imagine you add 'wolf' to the enemy list - well, it shares some attributes with werewolf, so you'd want to consolidate those into a shared base class, eg. 'WolfLike'. Now you add 'Human' to the enemy list, but werewolves are sometimes humans, so they share attributes too, such as walking on 2 legs, being able to talk, etc. Do you create a 'Humanoid' common base for humans and werewolves, and do you then have to stop werewolves deriving from WolfLike? Or do you multiply inherit from both - in which case, which attribute takes precedence when something in Humanoid clashes with something in WolfLike?

The problem is that trying and model the real world as a tree of classes is ineffective. Take any 3 things and you can probably find 4 different ways to factor their behaviour into shared and non-shared. This is why many have turned to a modular or component-based model instead, where an object is comprised of several smaller objects that make up the whole, and the smaller objects can be swapped or change to make up the behaviour you want. Here you might have just 1 Enemy class, and it contains sub-objects or components for how it walks (eg. Bipedal vs. Quadrupedal), its methods of attack (eg. bite, claw, weapon, fist), its skin (green for trolls, furry for werewolves and wolves), etc.

This is still completely object-oriented, but the notion of what is a useful object is different from what used to be commonly taught in the text books. Rather than having a large inheritance tree of various abstract classes and several concrete classes at the tips of the tree, you typically have just 1 concrete class representing an abstract concept (eg. 'enemy') but which contain more concrete classes representing more abstract concepts (eg. attacks, skin type). Sometimes these second classes can be best implemented via 1 level of inheritance (eg. a base Attack class and several derived classes for specific attacks) but the deep inheritance tree is gone.

But maybe classes are too heavy to be practical, I don't know...

In most modern languages, classes aren't 'heavy'. They're just another way of writing code, and they usually just wrap the procedural approach you would have written anyway, except with easier syntax. But by all means, don't write a class where a function will do. Classes are not intrinsically better, only where they make the code easier to manage or to understand.

1
source | link

I reckon it would be cool that both troll and werewolf inherited its attributes from enemy and overwrote some of them.

Unfortunately this approach to polymorphism, popular in the 90s, has shown itself to be a bad idea in practice. Imagine you add 'wolf' to the enemy list - well, it shares some attributes with werewolf, so you'd want to consolidate those into a shared base class, eg. 'WolfLike'. Now you add 'Human' to the enemy list, but werewolves are sometimes humans, so they share attributes too, such as walking on 2 legs, being able to talk, etc. Do you create a 'Humanoid' common base for humans and werewolves, and do you then have to stop werewolves deriving from WolfLike? Or do you multiply inherit from both - in which case, which attribute takes precedence when something in Humanoid clashes with something in WolfLike?

The problem is that trying and model the real world as a tree is ineffective. Take any 3 things and you can probably find 4 different ways to factor their behaviour into shared and non-shared. This is why many have turned to a modular or component-based model instead, where an object is comprised of several smaller objects that make up the whole, and the smaller objects can be swapped or change to make up the behaviour you want. Here you might have just 1 Enemy class, and it contains sub-objects or components for how it walks (eg. Bipedal vs. Quadrupedal), its methods of attack (eg. bite, claw, weapon, fist), its skin (green for trolls, furry for werewolves and wolves), etc.

This is still completely object-oriented, but the notion of what is a useful object is different from what used to be commonly taught in the text books. Rather than having a large inheritance tree of various abstract classes and several concrete classes at the tips of the tree, you typically have just 1 concrete class representing an abstract concept (eg. 'enemy') but which contain more concrete classes representing more abstract concepts (eg. attacks, skin type). Sometimes these second classes can be best implemented via 1 level of inheritance (eg. a base Attack class and several derived classes for specific attacks) but the deep inheritance tree is gone.

But maybe classes are too heavy to be practical, I don't know...

In most modern languages, classes aren't 'heavy'. They're just another way of writing code, and they usually just wrap the procedural approach you would have written anyway, except with easier syntax. But by all means, don't write a class where a function will do. Classes are not intrinsically better, only where they make the code easier to manage or to understand.