When in doubt, it is usually better to prefer composition over inheritance. Still, that is just a heuristic, not a law, and asking if this heuristic applies to your specific case is definitely justified.
Here is a simple argument why I think you should prefer composition in this case: if you want to keep your design open to make Drawable
a base class of certain more specific "drawables" inside your library (like 2D or 3D drawables, or OpenGL vs. DirectX drawables, or some other kind of technical classification), use composition. That will allow it to let the technical inheritance hierarchy stay orthogonal with any kind of domain specific inheritance hierarchy outside your library, where ProgramObject
may be the base class of certain domain specific classes (like a player character, or a vehicle, or some kind of other object).
This article here calls these aspects different dimensions:
When you have a situation where either composition or inheritance will work, consider splitting the design discussion in two:
- The representation/implementation of your domain concepts is one dimension
- The semantics of your domain concepts and their relationship to one another is a second dimension
In general, inheriting within one of these dimensions is fine. The problem becomes when we forget to separate the two dimensions, and start inheriting across inter-dimensional boundaries.
And this is exactly what would happen when you start to inherit a ProgramObject
from a Drawable
: you would mix up the "drawing" dimension with domain concepts, which can easily lead to a very unflexible design, where one will run into trouble when trying to separate technical and domain specific concerns.