I eschew inheritance except for when two objects or libraries are very much the same thing but the implementations are different. Just an example, where I might want to have the opportunity to use two different PDF libraries.
Further, there's a case where a number of objects share some common methods and you may decide to implement an AbstractWindow where those methods can live. But, you may find that Aspect programming works better in that case.
Generally, and perhaps surprisingly you shouldn't use inheritance in most cases. But inheritance is nonetheless a very important part of OOP.
It's funny, because OOP came my sphere of awareness around the same time that desktop software was beginning to use it for extensible GUIs. I'm talking about Turbo Pascal's Turbo Vision, and whatever Turbo C++ had.
That actually slowed down my comprehension of OOP. I thought OOP was for GUI work. OOP added so much complexity to the GUI code, and the GUI code added so much complexity to the OOP concepts, that it actually set me back by quite a bit! :-)
Mind you, it didn't help that, just as I was grasping crucial OOP concepts (e.g. a pointer to base class can point to an instance of child class), my instructor told me that was wrong and that I didn't understand OOP...
> ...my instructor told me that was wrong and that I didn't understand OOP...
Ugh.
I wonder how it should be taught then? Looking at the comments in this thread, it looks like a lot of people are simply choosing to use it in ways that make sense to them. Is there a universally-agreed-upon use case for OOP? If not, is there anything wrong with just teaching it as one of many tools, and letting students sort it out on their own?
I've tutored a few kids on programming. OOP has been my least favorite part every time. I honestly have no idea how to approach it as an occasional instructor.
I think a simple example from GUI programming would do much better. How about window classes? I did something like this recently:
Easy enough. What if I want a modal window though? Almost everything in it would be the same as a regular window, except I might need to do some things slightly different for show()ing and close()ing the window. Aha! A perfect example of an appropriate time to create a subclass: Programming tends to attract practical individuals. I think teaching "car extends vehicle" then is usually going to cause one of two results: either a student that then uses that approach all the time, even in cases where it's not warranted, because they don't understand when it's appropriate and when it's not; or a pragmatic student that resists using it because the given examples don't apply to anything that they're actually going to have any chance of working on.