Holy crap. I’ve been a software engineer for thirty years, I’ve been working exclusively in Java for well over ten years, and most of those explanations are nearly impenetrable.
Let me try to put it in actual layman’s terms:
In any computer program, there are two kinda fundamental concepts: things and actions. “Actions” are what you want done, “things” are what you want those actions done to. “Things” are usually referred to as “data”. “Actions” are called variously: procedures, functions, methods, messages, and other names.
So, as a trivial example, if I want to add 2 and 3, then “add” is the action, “2” and “3” are the data. And the “result”, “5”, is more data.
In procedural programming, the programmer basically thinks in terms of the actions. To implement addition, you write a function to perform the “add” action, and you give that function the two pieces of data it needs to act upon.
In object oriented programming, the programmer thinks more in terms of the “things” (data), which are called “objects”, hence the name; the programmer is more “oriented” to the objects as opposed to the actions (as in procedural programming).
So, in our trivial example, in OOP, the programming would need to define something that contained a number. Let’s call this a “Number” object. For our purposes (again, just to serve the needs of the trivial example), there are two actions that the Number object needs to be able to do: It needs to be able to take on a specific value, and it needs to be able to add itself to another Number.
In more strict OOP parlance, we’d say that the Number object needs to respond to two messages: “assign a value to yourself”, and “add the value of this other Number to yourself”.
So, in this trivial example, OOP sounds mostly like all it does is cause the programmer more work.
But in a less trivial example, suppose you’re writing a program that is going to deal with buildings. A building contains rooms. Rooms come in different sizes and shapes. One of the things your program should be able to do is to calculate the square footage of a building. The typical way to do that is to calculate the square footage of each room and then add them up (we’re simplifying here, don’t bother me with details about wall sizes). Suppose the building has both rectangular and triangular shaped rooms. The way you calculate the size of a rectangular room is different from the way you calculate the size of a triangle room.
So, in procedural programming, to accomplish this task, you’d need to have something like an array that holds information about each room. For a rectangular room, you need the width and the length and the area is found by just multiplying them. For a triangular room, you need the base and the height, and the area is found by multiplying them and then dividing by two. Hmm. In both cases, you need two numbers, but the meanings of those numbers, and more importantly the calculation that you do, is different. So each element of the array could hold two numbers, but you’d need something else (either in each of those elements or elsewhere) that told you what kind of room that element is for. Then, to calculate the are of the whole building, you’d need to loop through that array, and for each element ask what type it is that you could then do the right calculation.
In OOP, on the other hand, you define a type of object called a “Room”. You then define two sub-types of room called “RectangularRoom” and “TriangularRoom”. Each of the sub-types encapsulates the data about the room’s measurements and, very importantly, also encapsulates the knowledge of how to calculate the area. Each type of room understands the message “tell me your area”. But in the case of the RR, it multiplies its width times its length and tells you that; in the case of the TR, it multiples its base times its height and divides by two, then tells you that.
So, now, finally, when the “Building” object is asked for its area, all it needs to do is ask each of its rooms for its area, add them all up and tell you the total.
That’s one of the powers of OOP. The Building doesn’t need to know which room is rectangular and which is triangular in order to get the total area. All it needs to know is that a room can be asked for its area, and will calculate it correctly.
One other power of OOP is that, suppose you now encounter a building with a round room. All you need to do is write a “RoundRoom” object that holds just one piece of data, it’s radius, and responds to the “tell me your area” message by squaring its radius and multiplying by pi. The Building object doesn’t have to be changed at all, it still just asks each room for its area. The fact that a new sub-type of Room has been added is irrelevant to the Building (at least in this case).
Compare to procedural programming where, to add a round room, you’d have to add another specifier to whatever it is that indicates what the room type is, you’d have to add another branch in that loop that asks if the room is round, then does the appropriate calculation, etc. Much messier.