Others here have made good points, but let me offer a slightly different perspective.
If you have behavior (not code or traits, mind you, but actual behavior) that is common among objects, consider an abstract class with some established behavior in methods (possibly declared final
). But be careful. Look up the Circle-Ellipse problem to see why Circle probably shouldn't inherit from Ellipse even though that seems obvious to do.
You can only extend one class, so make it a good one. Keep in mind though that good software design is about coupling your code as loosely as possible. In other words, be as sure as possible that changing the code in one class doesn't involve changing the code in a bunch of other classes. That's why working over the weekend happens. There is no tighter coupling than inheritance, so choose wisely. Adding new behavior to a base class means every derived class gets it too, and that can lead to a lot of awkward problems (solved, for example, by implementing an empty method just to satisfy the contract).
Finally, the ability to extend multiple interfaces allows client code to treat an object differently according to a different API contract, so I can treat a Person
object as a Doctor
in one part of the code and a Father
in another part of the code. But make no mistake, this is not multiple inheritance.
In the end, it depends on your domain, the possibility of changes to your base classes, and other factors that you will learn to measure with experience. All things being equal though, prefer interfaces to inheritance.
And wait until you learn Ruby and Scala and you get to learn about modules and traits. Then it gets really fun.
Hope that helps.