It\'s been years since I thought of this, but I am training some real juniors soon and need to explain what an object is to someone who doesn\'t know what it is.
B
If you want something really useful, don't forget to explain why. That's a concept that seems to be frequently missed - why is this useful...
I like the "Vehicle" example. Many things can be vehicles (abstract class), but they all have something in common - they can move from a to be at some speed. Then there can be different classes of vehicles: gound vehicles, some moving in water, some in the air.
So you have another level of abstraction - all vehicles in the air for example need an altitude member.
I guess you get the picture. This explains most of the points you've given above.
The animal/car metaphors exist to explain the philosophy of object oriented design, which is far more important to understand than just the implementation.
If you skip the metaphors and start with just "it's just variables and functions to deal with them", you're missing any description of responsibility. I constantly deal with developers who give no consideration to class responsibility (see CRC Cards), but instead put data and methods into classes wherever they happen to be editing at the time.
You also miss out on "tell, don't ask". The animal metaphor works well here. In OO, I tell the dog to clean himself. I don't ask him how he's going to do it, because that's a black box I don't want to see inside. The dog knows so I don't need to.
Just be sure to teach your students that these are just metaphors, not the actual thing. A "perfect storm" in the "mortgage meltdown" does not actually involve either storms or anything melting.
Back when I was learning OOP, I was puzzled by all these "car / animal / whatever" metaphors. They didn't help me at all. Then someone said that a class/object is just a set of variables (class members) and functions to deal with them (methods) - which is actually true. It was that simple!
Using all these popular metaphors is just misleading people, IMHO. Cars don't have that much in common with OOP. It's easy to understand these metaphors when you already know what they mean, but trying to begin with them... no.
I would go by Grady Booch definition: An Object is one which has a State, Behaviour and Identity. Member variables contribute to State; Methods contribute to Behaviour and some unique attributes contribute to identity. For eg., email could be an identity attribute for a Person Object.
As always, it really does depend on the language background they're coming from. Not every language implements OO paradigms the same way, sometimes it's possible to use an OO approach in a language that isn't stricly OO at all.
Generally, access levels are important to mention. Why should properties generally be private? What's the point of having getters and setters? This is a good place to contrast objects with collections like maps or arrays (even if they can be implemented as objects rather than primitives).
Inheritance and polymorphism should go hand-in-hand. This is a matter of abstraction, though. Explaining the difference between abstract base classes and interfaces is probably more of a language problem again -- some languages allow multiple inheritance, others only allow multiple interfaces.
Encapsulation is pretty straightforward if you got the access levels sorted out. Again, depending on the language you might want to explain inner classes and such, abstract the OO idea even further with anonymous classes maybe.
I find what works best is to start with something familiar: related functions and variables. Learning what should be an object and what object a property or method should belong to is tough, so start with clear cases.
A database handler can be a good example, or maybe an email (create a new email, set its headers and content, attach files and send it -- pretty straightforward and familiar even to non-programmers, but a perfect example for thinking in terms of objects (email, contacts; maybe even mailboxes, servers), methods (create, send, attach, set) and properties (headers, content, attachments)).
What's important is this: even if your students have some (non-OO) programming background, adjusting to OOP is a process, but "getting it" often isn't. I've heard many people describe it as a sudden event rather than a smooth transition. Of course the "calibration" is a long-term process: you need to figure out when it makes sense to create new classes and when a few temporary variables, an array or utility functions (depending on your language) will suffice, but this needs practice, not teaching.