Hi Jack,
touchy subject. Inheritance vs. Delegation/Composition.
Here are some tips that I have stumbled upon and learned from others:
"If I already have a class that performs almost all that I require, would it be better to write a new class that inherits from the current class"?
Well it depends. Don't force your designs to rely on inheritance just becaue a class needs functionality already present in another class. Inheritance should be used cautiously in situations where there is a true "is-a" relationship. For example, one might be forced to derive a square from a rectangle. They are both shapes, they can both draw and color themselves. Thats enough to warrant inheritance. But is it? Lets look closely at the domain logic of maintaining aspect ratio as we increase the width and height of a square vs. rect.
The domain logic for aspect ratio for
square says:
- As height increases, width also increases proportionally to maintain it's squareness.
A Rectangle says:
- As my width increases, my height can stay the same. And vice versa.
Imagine a square inheriting from a rectangle to reuse base functionality and overriding the resize() operation to follow squareness. It deceives a client trying to use a square as a rectangle, a client unknowingly expects the square to behave as a rect because it follows the bloodline of a rect after all, clear violation of LSP.
Now ofcourse we all know the difference between both shapes, but in cases where the domain model is different, you have to watch out for this.
If you can confidently say "is-a", then the bloodline can continue, and only override to produce the same domain logic, giving the clients what they expect when they substitute a base for derived.
Delegation is a better approach in cases where there is no bloodline to follow but you need to share existing functionality. In that cause you can use Delegatioin.