Game Objects: Inheritance VS Composition
From Sidvind
Contents |
[edit] Description
Each game must have a way to structure the objects of the game.
For quite a while I thought about inheritance and composition. I had used inheritance for a very long time but when I started to design a "real" engine I had to make sure to think through every architectural decision. This was one of the major decision so I thought I would share some of my thoughts.
[edit] Inheritance
As I see it the most basic and probably the method used by most new game programmers and even in couple of real engines. With inheritance all objects derive from each other and all share a common baseclass. Since an image says more than a thousand words here's one:
With inheritance we quickly get many classes that often is derived many times. Imagine how such a tree would look like with 400 different objects and 10+ levels deep. The good part however, we can store the position vector once and share it between all components (physics and graphics for example). Inheritance is also easier with few objects and/or few components. But what happens when we need lots of different objects with many components, say graphics, physics, sound, logics, network etc? It's really hard to create a wooden crate with only physics and no logic or sound, and at the same time have one that has those. We would need to create an entirely new branch of the inheritance tree.
When it comes to implementing the classes we get a lot of header dependencies . Each class includes many others, at least one per depth in the tree. Of course, with composition you would still require this but we will see why composition has fewer dependencies anyway. One might think that we could avoid this with forward declaration but you cant. When inheriting we must know what the parent looks like.
Another thing we want to avoid is lot of coupling. As an example there is a risk that each object "talks" with the graphics manager directly. That is bad coupling. Period. Just imagine the coupling in the eaxmple above, lots of objects with may components. And what do you do when the interface for the graphics manager is changed? Bad coupling indeed.
[edit] Pros
- Easy with small trees
- Less memory consuming and no overhead with calling different components.
[edit] Cons
- Dependencies
- Large inheritance trees
- Can get really complex and confusing
- May lead to bad coupling
[edit] Composition
Composition is a design pattern which can be used to avoid inheritance when used as above. You would still require a class for each object but you don't have to create an entire branch just because you need that wooden crate with no logics. We don't need deep trees at all. "Object -> Entity -> Wooden Crate" is enough. This is the major reason there isn't large header dependencies when implementing the code. The inheritance trees wont be complicated at all, they wont contain all those abstract classes we needed with just pure inheritance.
So, what exactly is composition? To make it simple, each drawable object has an instance of a class that has no other purpose that draw itself. For each component an object has it has an instance of such class.
| Code: Composition example |
class WoodenCrate: public Entity {
public:
...
private:
Pawn* _pawn; // The visible object
Physical* _physics; // The physical properties
Sound* _sound; // The object we can hear
};
|
[edit] Pros
- Few(er) dependencies
- Less coupling
- Can be combined to create new objects easy
- Easy to unittest
- Follow the basic rule of "Is-a vs Has-a"
[edit] Cons
- More initial work
- Consumes more memory
[edit] Conclusion
Use composition unless
- your game is really small, or
- you cannot afford to waste a single byte of memory, or
- you have no performance to work with.

