imo one of the core success factors of a software development project is the initial design of the Object Model. This needs to be done right as soon as possible (which implies inclusion of strong business / systems analysts - but that's for another discussion), because changes to the model after implementation begins has serious consequences to the project time-line (and the budget)
One of the core design "anti-patterns" that I have been witness to, has been the over-zealous employment of inheritance in the model, which results in a complex design, which takes longer to implement, which creates havoc when a change is required (and it will be required - rarely is the object domain fully understood the first time round)
Hence follows a guide on inheritance which should be followed during the design process:
Only inherit when:
1) The derived object introduces new attributes - properties
2) The derived object introduces new behaviour - methods
3) The derived object introduces new relationships with other objects - which really is just a variation of 1) and implies the necessity of 2)
ie: an object "dog" can be of type "poodle" and "greyhound", but that does not justify adding a derived object for every type of dog if they do not satisfy the above rules - an over-simplification, but I have seen this done time and again in the business arena to the detriment of the software development effort.
If logic needs to be executed which depends on the specific "type", and none of the above rules are true, then type needs to be an attribute on the object, not a specialized type. This way, when types get added / removed after implementation, there is no need to change the model.
So don't be caught only using the "is-a-kind-of" guideline for inheritance - it can lead you down a very timely and expensive path.
Now, keeping the above in mind, go and
read more on what inheritance is all about.