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.

Based on what you use in the real world, what are the key points of objects that I should focus on explaining. For example:

  • Access Levels
  • Inheritance
  • Encapsulation
  • Polymorphism
  • Abstraction
  • Interfaces
+13  A: 

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...

This was my problem in maths class in school, really. With OOP the answer can be really easy: abstraction, re-usability, centralisation, easier maintenance, etc etc. But the tough part is selling it -- there's enough snake oil in programming paradigms that programmers tend to be sceptical when it comes to changing their way of thinking.
I meet a lot of developers who 'know' OOP, but have no idea of what the benefits are of using it. Most seem surprised to learn that it doesn't actually make initial development 'faster'.

Use real life examples.

  • Animal (interface)
  • Mammal (abstract class)
  • Dog (class)
  • Your dog (object instance)

access levels: And your mom can't touch your privates, but your friends can.

Please, don't. The problem with analogies is that they never work.The first article I read on OOP tried to use a bike analogy. Others have used car analogies. While the idea of "a car has properties like colour, contains other objects like its engine and has methods like startEngine()" is nice if you are looking into abstracting real world objects in a programming language, it didn't do anything for me to help me think of PROGRAMMING in OO terms. A better approach is based on programming terms -- assoc. arrays or maps are a good start.
@Alan: an approach based on programming terms only works on an audience of programmers. Analogies are very useful, nay, essential fpr explaining very basic things like what is meant by the term "object" too the lay public (which I would consider the OP's audience). Just don't use them beyond the 101 is all.
My mom can't even see my privates, let alone touch them. ;-)
Nick Presta
There are plenty of good examples, but animals or cars aren't among them. Use an example that makes sense in the context of a program. There are so many concepts that it make sense to model as classes. Even a trivial program is full of abstractions, of data that is supposed to behave in a certain way. Internally it may just be two strings and an int, but it has associated behavior, and operations that are legal, and those can be meaningfully abstracted into a class.
Animals or cars are actually excellent as OO examples - just NOT in the way they are commonly used. That is, don't try to model the animal/car itself, rather attributes that might actually be relveant to your software. For example, discuss a program for zoo management - then you need to model the types of animals, their feeding schedule and content, where they can be in relation to other animals, what kind of protection you need around it, etc.... or management for a car rental company, you need to model mileage, seats, taxes, licensing, etc... Car.start() or is really not clear.

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.

Thorsten Dittmar
I've preferred the Person/Student/Male/Female/Cousin/Etc..., since it makes multiple inheritance and some design patters (such as decorator) easier to explain IMO.
Ben S

I prefer using real-life examples that you can actually interact with: a dish-washer, a car, ...

These things also happen to have a very strict interface: a car (in Europe :)) has an Acceleration pedal, a Break and a Clutch. You can ask for it's current speed.

Encapsulation: no need to know how the engine works if you know the interface. A good thing that you don't have to tinker the engine yourself, too.

Polymorphism: you can drive a Lada and a Porche using the same interface. This means you are a polymorphous driver :).

Note: it's taken me years to differentiate the concept of an interface from inheritance. I would say: leave inheritance out for a while: most of the time code reuse is achieved better by composition (though that's a whole other discussion).

strict interface? On some cars I can open four doors, on others I can only open two. On some I can play back CD's, on others I can only receive radio. A car only has a "strict interface" in dumbed-down and contrived programming examples. ;)
The driving aspect can have a very strict interface. The cargo aspect can have another strict interface, which allows change in the type of cargo (passengers?) and the number of doors. I tend to dumb-down my business logic as much as possible in order to keep complexity under control.
+35  A: 

I like the original metaphor used by Alan Kay, who coined "object-oriented programming": Objects are like cells in a body. They are each programmed with their own behaviors and communicate by passing messages to one another, which they again respond to with their own internally defined behavior. No one cell knows what's inside another — they just know how to handle their own tasks and communicate with each other.

Agreed, encapsulation is the defining characteristic of objects. Everything else is an optional extra.
I've always found the message-passing explanation appealing, but misleading. It gives the impression of something more like "Actors" (a.k.a Active Objects), which might have been accurate for Simula, but that's not actually how most OOP languages work. Usually (SmallTalk, Objective-C, Java, Python, C++, ...) "sending a message" is just obfuscation for synchronous function calls.
And synchronous function calls are just obfuscation for pushing binary data through the processor that happens to accomplish the goal of the original code. From a design standpoint, it's messages. Just because the actors aren't working in a multithreaded system doesn't mean that isn't conceptually what's going on.
For a second there I thought - huh? The passing-messages made it sound like asynchronous, but if you add that these messages are synchronus - one pauses and waits for the other to finish, then continues - this is much clearer.
I'd say cohesion is the defining characteristic of objects--related items go together. It's possible to have objects that don't make use of encapsulation--it's just usually a bad idea ;) .
In the Common Lisp Object System, a class will encapsulate its data members, but not methods. This allows methods to be called based on the actual type of more than one argument, which turns out to be quite useful. There are more variations on OO programming than those in C++, Java, and C#.
David Thornley
+101  A: 

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.

Joonas Pulakka
+1 - I really liked this answer. I would have given more votes if I could.
The animals thing is mostly used for explaining (abstract) inheritance it seems, which I still think is a useful thing but doesn't hold up so well with modern composition/interface driven OO. It neglects too many other facets.
Agreed. The popular car analogy doesn't really work well. For example, the method car.startEngine() already causes a lot of trouble: if you start the engine, aren't you interacting with the engine? So you would probably want to rephrase it to car.turnKey(), because that doesn't put as much emphasis on the internals, but now you introduce a new object (the key), so it should really be key.insertInto(car) (or is it car.insertKey(key)?) followed by key.turn(clockwise) -- and that's just for STARTING the car.
Or you could have just made Engine a member of Car and called Car.Engine.Start()....
+1 - My first thought as well.
David Robbins
Or you could just say car.start() and stop trying to violate the car's encapsulation.
Terry Wilcox
"Car" metaphor helped a lot to me. Give it a try. :)
Arnis L.
Animals or cars are actually excellent as OO examples - just NOT in the way they are commonly used. That is, don't try to model the animal/car itself, rather attributes that might actually be relveant to your software. For example, discuss a program for zoo management - then you need to model the types of animals, their feeding schedule and content, where they can be in relation to other animals, what kind of protection you need around it, etc.... or management for a car rental company, you need to model mileage, seats, taxes, licensing, etc... Car.start() or is really not clear.
Maybe you could use examples from the code base the juniors will be working on (or from your own experience with previous projects if it's green-field development).
+1  A: 

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.

+5  A: 

I would go from Access Levels and Encapsulation and move out from there. Encapsulation is a reasonably simple concept to grasp and has some clear benefits. From there you can talk about abstraction, inheritance and polymorphism quite easily.

As an undergraduate I found Encapsulation to be an good anchoring concept in a quite abstract area.

+3  A: 

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.

Of course, not all objects need behavior or identity...
Or state, for that matter...
I'm curious as to when an object doesnt have an identity or a behavior or state to still be considered an object? The very definition of an object that I'm aware of (Grady Booch's definition) is that object has an identity, a state and a behavior.. if it doesn't then it's something other than an object, such as an attribute (color)..
+1  A: 

I prefer the approach used in "Object-Oriented Design and Patterns" by Hortsmann. If I recall correctly, the approach was to read a problem statement and identify the objects, their methods, relations, and other components using a simple pattern. For instance, an object is a noun, so all nouns would be candidate objects.

The book itself is highly recommended. After establishing what an object is, it uses some clearly defined and simple examples to discuss inheritance, interfaces, and many design patterns like the singleton. I guess I really suggest you let someone else do it... an author(ity).

Tim Bender
+10  A: 

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.

Terry Wilcox
This thread just reaffirms my belief that developers are learning terminology rather than concepts.
Terry Wilcox
+1  A: 

If I were trying to explain classes and objects to someone completely unfamiliar with programming, I would probably use something along the lines of the following:

A class is just a "recipe for a thing", the class is made of different types of "ingredients" that have different characteristics (i.e. PODs and functions/methods).

So, in that it only contains descriptions of a layout (building blocks) and functionality.

Ingredients may be of different type: "data" in that they contain actual data fields (think facts stored in variables/fields), and "action" in that they contain specific methods to do things.

Some ingredients may be secret, you may not want to share all ingredients or you may not want to share some specific ways of doing specific things with the recipe (encapsulation).

So, you as the cook have the possibility to restrict access to ingredients, so that users of your recipe have to adhere to your recipe and simply use "pre-canned" steps (methods) of doing things that you provide (without them necessarily knowing what it is about):

Some ingredients may be meant to be only internally visible (private access) because they are only really relevant to that specific instance/manifestation of the recipe/class, while others may also be meant to be accessible from recipes that are based on this recipe (think customizations), that derive from it (protected access).

And then there are ingredients that shall be generally visible and accessible to all users of the recipe (public), because they compose the "frontend" or "interface" of the final product (they don't necessarily need to know about internals/low level implementation stuff).

Once a class is actually used to implement a particular recipe, a new object is created (the class gets instantiated): A chocolate cake is just one manifestation/version of the chocolate cake recipe. There can be many other versions using the same "recipe".

If you were to combine multiple recipes (e.g. chocolate cake and lemon cake), you can create a new recipe that derives from both recipes, basically creating a completely new recipe that shares the characteristics of the original recipes (multiple inheritance).

By basing new recipes on existing ones using inheritance, changes in the original recipe can be directly imported into the new recipe. Similarly, having a common ancestor recipe (type/super class), means that its very properties (fields and methods) can be expected in all sub classes (inherited/child recipes), in other words a generic "chocolate cake recipe" might be used to create two new specialized versions of a chocolate cake: "white chocolate cake" and "dark chocolate cake", where the color of the chocolate merely becomes an attribute that may be configurable using a chocolate cake specific method like "setChocolateColor()".

If you want your recipe to provide a way for new recipes to override some components of your recipe, you can provide boilerplate actions (methods) that can be individually overriden (virtual inheritance).

Danny Varod
+1  A: 

objects (usually) have state, behaviour, and identity.

basic o-o programming principles are encapsulation, inheritance, and polymorphism.

basic o-o design principles are here:

Ray Tayek

I prefer to think of Ants - it gives visual learners something to "see" and you "tell" for the auditory learners. Focus on the WHY for each part first to avoid the glassy eyes.

Ant derives from Insect (Inheritance) Worker Ant, Queen Ant, Drone Ant all derive from Ant (Inheritance). There is no generic “Ant”, all ants are from the derived classes of Worker, Queen etc but they all have the same basic Interface –actions (methods) and Properties.

Worker Ant, Queen ant, Drone Ant derive from Ant and thus exhibit ad-hoc polymorphism where they all derive from the same Ant class and exibit subtyping polymorphism (Inheritance) of the Ant class, these ants are all a subclass of the Ant class and inherit the 6 legs, 2 eyes, 3 body segments etc. of the Ant – the Properties. Ant also has methods, walk, see, and grab ability of the Ant class. Thus the appplication of the implimentation of the Interface of the more generic Ant class (Polymorphism) with the properties and methods of the basic Ant class, but each subclass defines how it implements those.

Worker Ants have different activities and behavior. They Gather food, Protect colony, Dig tunnels, Care for Queen Ant etc but still have the base attributes of Ant (Interface). Jaws are used in each behavior - polymorphic function which is NOT Polymorphism in itself and thus you get the idea of, method overloading for the different use of the Jaws – each method has basic similarity (jaws, grab) but different object types are used – grab dirt, grab other ant, grab food, grab gunk off queen, grab enemy. This shows a WHY of overloading methods, - areas of specialization depending upon what is grabbed – larva (young ants) and food are handled gently and differently than the enemy where we want to rip them up.

Each Worker Ant is an Instance of an ant, separate but with similar behaviors and different task/state at a given time, so given the tasks, they can be on different threads. If one ant on a food-gathering mission (thread) dies, the other ants keep seeking food, as they are not dependant on the dead ants survival.

Each Ant has access and ability to manipulate its own Private attributes, legs, eyes and so forth, but not to manipulate other ants eyes and legs (Access Levels).

Ant Colony – the overall namespace for the Ant – thus the Queen Ant and Worker Ant might belong to the Ant Colony namespace, and the worker ants have access to the Queen Ant but nothing outside does (Protected)

Queen ants never go outside normally – (Access Levels)

Each Ant has access and ability to manipulate its own attributes, legs, eyes and so forth, but not to manipulate other ants eyes and legs (Access Levels). Now this ant knows where its legs are, where it is looking, those are Encapsulated within its instance. The act of Encapsulation creates Abstraction to some degree here.

By using the concept of Encapsulation we can Abstract and thus we can send the Worker Ant off to get food, but we do not have to care how the ant gets the food, only that it returns with food, we have isolated the details of the activity from the result.

You can impliment the examples in the language of choice for your audience. If this helps one person, I am satisfied :). I hope I have not confused myself :)

Mark Schultheiss
+1  A: 

I would try starting with actual code. Hopefully they're at least slightly familiar with some language. Write a simple program without using any classes or OO design at all, and then show how it can be made clearer or easier to maintain or whatever, if you redo it using classes.

A good example would probably be something where there are several functions that all use the same set of variables. For example (this is just the first example I could think of. You could probably think of much better ones -- hopefully something that doesn't seem too contrived and resembles something that you would actually write for a real-world project):

void printContactInfo(String name, String address, String phoneNumber) {
    System.out.println(name + " lives at " + address + " and his/her phone number is + "phoneNumber");

You write the code above, then at some point later, you decide that you'd also like to include the person's email address and username. Or you are dealing with two different people. You could easily end up with unwieldy functions that take several arguments, or have zillions of variables to keep track of. Or you could write a Person class, and you'd just call:

Person someguy = new Person("MatrixFrog", "123 Notareal Street", "555 5555");

Again, probably not the best example. And I do agree with mad-j that these little "car" and "person" examples aren't always great. But I think if you presented the example as a solution to an actual problem that comes up while writing code, it might be clearer.

Same thing with inheritance. The idea is based on the real-world understanding that "An X is a certain type of Y" but the reason we do it is to make code easier to read and write. I don't think I really understood inheritance until the first time I found myself writing two classes with a lot in common, and thinking, "Wait. These have a lot of the same properties. Maybe I should put their common properties into a superclass!"

+1  A: 

Sometimes it is hard for beginners to understand how objects relate to program execution. ("Ok, I have a Person object I can instantiate as 'Jerry', but where do I perform the instantiation? What creates Jerry? Ok, then what creates that? Where does it all start?")

Try a universe analogy. The types in your program represent, at various levels of abstraction, all the possible objects that can exist in the universe. Make sure to show them the big bang (program entry point)! This will also show them why global variables in OOP don't make sense. Then you can dive right into OOP principles.

Sam Pearson

From my own experience, I think the idea of an object or class merely being an instance of a thing or a description of a thing can be quite adequate for an initial abstraction. What the thing has, i.e. members and/or properties, and can do, i.e. methods, are the next level of things to add. Then comes the inheritance, abstraction, encapsulation and polymorphism ideas as ways to round out the initial take of modelling that OOP tries to do. I came to OOP from a procedural coding background so the idea of customizable variable types does create a lot of different ideas that can be explored.

JB King

I would use one example through the whole thing to build up the concept instead of jumping over unrelated examples.

That magical example would be GUI.

GUI made a lot of sense when I understood OOP after a lot of struggle.

A window is an 'object'. a button is nothing but a fancy way to say a rectangle drawn in a special way (abstraction). A window 'has' buttons. A hyperlink label 'is' a button. every Clickable thing on my Screen is a button (Interfaces). All buttons when clicked go to Stack overflow (inheritance). Except one button, which goes to Server fault (polymorphism).

And the hard part, 'Encapsulation' which is nothing but a fancy way to save the programmer from debugging :)

In the end I would stress that OOP is not the end of the world, If it does not make sense to think about something as an Object then it is NOT an Object. Because I have seen a programmer trying to build a mergesort class :D



IMHO we must first get them interested in OOP before bombarding them with all the concepts in OOP. To make them get attracted towards OOP, explaining all the concepts in OOP or showing examples of cats and dogs will not work. You need to show them the advantages by comparing a problem solved the OOP and the non OOP way. Make sure you solve the problem first the non OOP way, highlight the disadvantages, use one of the concepts of OOP to solve it. It might probably employ only one concept of OOP, but if you are able to make them feel the advantage it holds over the other method, they would themselves be eager to explore more of OOP. You just need to point them in the right direction after that. Once they are familiar with the concepts, point them towards design pattern books like "Head first design patterns".

+1  A: 

To a beginner: An object is like a noun. If you're in a classroom then you have desks, students, teacher, projector etc. Each has characterists of their own and some commonalities.

So if we wanted to write a program that would behave in the same way as a classroom, we need to recreate all these 'nouns' in code. Each can do things (student::listen()) and they can interact with each other (student::search(new Desk()))

When we have defined all the rules and behaviours (i.e written our classes/interfaces) then we set them loose in the program. for(i=0;i<30;i++){class.Add(new Student()))} etc

David Archer
I'd make the point that any verb can be noun-ified and vice versa (like saying 'noun-ified')

I would try to compare the procedural programming paradigm with the OOP one. Even if your students are completely new to programming, I would show them some examples with 'primitives' and then the examples with objects. I would point the difference between a variable of a primitive type and an object of a class in that the type of the object may contain a number of variables (members). Of course at that point you should have mentioned functions, if they didn't already know them. In fact, in lesson one, I would explain the basic concepts of procedural programming (variables, types, functions) that are the basis for the fundamental concepts of OOP. After all, OOP is just a wrapper for procedural programming in itself.

After lesson one, along with explaining members of an object, you should explain methods as well. For "really junior students" I would focus on access levels, encapsulation and lastly on inheritance.

The real world examples, like car etc. can be used to show why it is good to have objects, but after exposing your students to the basic programming concepts. For your more talented students I would give out hints, like that an object is just an implicit argument to its methods, or that a member of an object is like a restricted global variable, or that an object is like a closure, etc. (that depends of course on your students and you need to make sure not to confuse them, so this last piece of advise is optional, of course :-) ).


I agree with mad-j's answer. Start with procedural programming in (whatever language) you are working in.

I think the whole objects first approach that many, many modern texts use today is wrong.

+2  A: 

One of the things I find many people get confused about in OOP are actual instances of an object. That you have the ability to create multiple instances of the same class, independent of one another, seems to blow peoples' minds. If you're going to go with the usual "physical object" analogy, make sure you talk about how you can have multiple instances of said objects and how they can interact with one another as well as with themselves.

For example, take the classic "car" example. Now you have your driver program "road" which has a "carCrash(Car car1, Car car2)" function. Explain how the objects interact with one another.

The only problem with analogies like this are that, in my experience anyway, they tend to break down when you start talking about static variables/functions. I guess what I'm trying to say is that no analogy is perfect, so try not to rely on them too much.

Norm MacLennan

I might start with anonymous types or something like JSON to demonstrate that objects are just collections of properties. Talk about cohesion.

What if we want a bunch of these objects? Classes/constructors/instances.
What about functionality? Methods.

Then demonstrate the problems that occur from a lack of encapsulation. Show how getters/setters/private fields alleviate the problem (maybe move to a typed language if you've been using JSON)...

Then show how inheritance allows code reuse--maybe show a sample of inheritance by actually re-typing (with the keyboard) the functionality to demonstrate what a pain it is. Show that you can change something in one authoritative place when things are well-designed.

Then introduce polymorphism--because inheritance is sometimes insufficient. Include interfaces here.

Try to use real-world examples--either from the code-base they'll be working on or from your own portfolio. As you go, demonstrate refactoring and other good practices. "Hey, I keep repeating this pattern--I should consolidate it somehow".


My experience as a self-learner is that I introduced a fair amount of trouble in my head with the concept of object as mapped to a "real entity" like animals and cars and so on. It forms your head in willing to find a realistic (as in "the real world") taxonomy in your business objects even when there's none, and it confuses you in finding unrealistic taxonomical classification that are instead useful for real OO design (eg. design patterns). Finally, it pushes you to the point that you fossilize in one "real world" taxonomy even if other "less real world" can exist and they are better.

In any OOP book you find that a square is a kind of rectangle, and so a square is represented as inherited by a rectangle, but we know that this approach is deeply flawed (I read a paper on that, don't remember where, but you can search about the "fragile base class problem" in google). Also, in some programming languages, you don't need OO taxonomy for interface inheritance (see my post on this regard).

So, my suggestion is: present it but be very careful how far you go, and eventually switch immediately from the "car and animals" examples to a less nice to present taxonomy. You can deeply flaw their understanding if you push it too far.

Stefano Borini

this question is interesting ... and very complicated ... because it depends on the language you use ...

  • take objective-c: an object has it's variables, only accessible from inside, and methods, such as accessors ... objective-c actually sends around messages between objects ... which gives comes at a certain cost, but allows lots of cool things, like proxies, mock objects, profiling, AOP and so forth ... in objective-c, a class is an object ... objective-c does not have the notion of access levels ...

  • take PHP ... there, classes are not objects ... objects have variables and methods ... and it's totally inconsistent ... :) ... just as a bad example ...

  • take Ruby ... there, everything is completely dynamic ... an object has its variables, only visible from inside, and a class, determining its methods ... you can modify that class at runtime, or even, you can assign a different class to that very object ... funky ... and also, in ruby, operators are methods of objects ... you have incredible language constructs like blocks ...

  • take ECMA-Script(JavaScript for example) ... here everything is an object ... functions are first class objects ... an object has a set of properties (fully dynamic), some of which may be functions, acting as the object's methods ... you may take the method of one object, and apply it to another instead (does not necessarily make sense, but it is feasible) ... any function may be used, to instantiate a new object ... and so on ... ECMA-Script does not have the concept of access levels, but you can hide away data using closures, if necessary ... ECMA-Script does not know classes ... but inheritance is achieved through its prototype based nature ...

i could go on ... but you see my point, i guess ... many languages implement only parts of all the things that most understand as OOP and emphasize different things ... sometimes it's a weakness, sometimes powerfull ... also the semantics, of what an object is, and what a method is, is VERY different ... to not confuse your students, you should really stick to one language, or languages having exactly the same semantics, when it comes to objects, and the describe what an object is ... otherwise, they will never actually understand you model ... once they got their head around it, you can show, how OOP looks in other languages ...

i think, you should take JavaScript or Ruby (although i think JavaScript is better, and then move on to ActionScript 2, to have a typed version of it, and classes, interfaces etc. ... or start with ActionScript 2 directly), to show concepts of OOP, since they are very radical, clear and simple ... or maybe other scripting languages ...

a thing not to forget is, that it's object oriented and not class oriented programming ... chosing a language, that does not need classes in order to have objects, seems a good idea ...

  • introduce objects as entities ... first just create some anonymous dynamic objects, give them some attributes and methods and play around ... maybe fiddle around with some built-in global objects, if any such things exist ... try to show, how thes objects can model a real world ... don't try to hard ... simple examples ... let them add a few methods on the run and experiment a bit ...
  • once they get a hang of it and really kind of understand what objects are, explain, what a type is, first on the builtin types (if you choose the right language, any value is an object ... i think that's a good way to go) ... then explain, what a class is ... an object, or maybe just a language construct, to create objects, that are similar and have the same type ... then explain subclassing ... don't inherit car from vehicle ... don't extend fruit with apple ... it's confusing ... you have a type of objects, and you have subtypes of that type ... as in real life, science, maths ... anything ...
  • then explain interfaces ... as a different kind of types, that categorize an object not by where it comes from, but by what it does ...
  • once that is really understood, talk about encapsulation and access levels
  • once they understood inheritance and interfaces, tell them, inheritance is cool for not writing a lot, but it does not solve all problems ... emphasize the importance of interfaces ... teach them to use interfaces as parameter types, whenever possible ... introduce composition, forwarding, proxying, delegation, etc. ... show them how nicely factories can be used to reduce dependancies on concrete classes ...
  • preach decoupling, and teach them ways to achieve this ... explain them, how to build their object hierarchies, so they don't wind up with a chaotic network, instead of a nice tree, where dependancies get ever smaller, as you go to the leaves ...
  • now you can safely move to languages, that are less sexy, but more mature ...

use a language, that is consistent and keeps code short and concise ... try to avoid situations, where you have n lines of code, that are mandatory, but you don't really have the time to explain them ...

in my opinion, introducing people to OOP first, is a good decision ... OOP is about modelling ... the higher the language, the more it teaches abstract thinking ... starting with procedural languages, where you maintain states in tons of variables scattered around your programm, is not good ... it takes a hell lot of time for people who really learned procedural programming, to move on to OOP ...

well, this was a little more, than i actually inteded to write ... hope it helps at least ... :)

+1  A: 

Stick with Booch's definition: An object has state, exhibits some well-defined behavior, and has a unique identity. I noticed that others posted this already, but people made comments regarding some objects not needing state, behavior, or identity which I disagree with. An object has state in the sense that some programmer defined amount of memory has been allocated for it, behavior in the sense that it can react to messages being sent to it, and identity in the sense that it can be assigned an identifier. Which actually sounds a lot like Kay's explanation of a lot of little specialized computers communicating with one another.

I also agree with the few posts that mention first understanding the concepts of procedural programming, because the work in an object-oriented program is still done at the procedure level. The difference is the level of abstraction at which the programmer can write the program. In object-oriented programming, programming at a higher level of abstraction is the ability for the programmer to make concepts that span state and behavior, in any combination, explicit. Which obviously requires an understanding of how to implement concepts using state and behavior.

The next major concept I would tackle is generalization. An object choosing which behavior to invoke in response to being sent a message, at run time, is what allows for generalization. Generalization occurs when a programmer hides the details of how to accomplish a similar concept in two distinct ways behind one uniform message.

From here I would move on to encapsulation, inheritance, and polymorphism. And from there on to more high level concepts. I just feel that keeping everything focused specifically around how these concepts help you solve problems is important for retaining them.