Object Oriented Programming -- What is it?

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.

A humble suggestion: if you don’t understand it, you probably don’t need to use it. I am not saying you’re stupid, I’m saying that OOP probably has little or no bearing on your life.

Having said that, I offer two more observations:
a) most programmers/engineers/techno-nerds can’t write worth beans. I speak from experience. I’ve been a software engineer, and I am now a technical writer. I have seen countless examples of people who thought they could write, but can’t. Most of them fail because they have no idea of how to explain something to someone who doesn’t understand exactly what they understand. Well, duh!
b) A lot of modern computer software is using OOP and object-oriented design ideas. Even if you don’t understand all the nuts and bolts, having a surface knowledge of OOP does help you do some pretty-high level stuff. For example, you can then understand how to use JavaScript to mess around with your web pages, or use Microsoft’s VBA to “program” Word, Excel, etc.

I now get to offer my humble two cents about why OOP is nice:
a) reusing other people’s code is way easier.
b) You don’t have to worry about all the awful details in order to use a sophisticated package of functions. I offer as an example the wonderfully named Python OOP-based library called “BeautifulSoup”. If you know a bit of Python and you follow the instructions, you can use the library to read and split up HTML. Well, I think that’s neat, and a lot more simple than having to do it yourself.
c) OOP-based libraries of functions/programs/whatever correspond very neatly to the structures that we use in modern computer life, like HTML tags/DOM objects/JavaScript.
The attributes of a tag (those options you put inside the <>) correspond to the “properties” of a DOM object, which you can then manipulate with JavaScript as if they were variables. Oooh! Shiny!

So I guess that in the end OOP is popular cuz a lot of software engineers look at it and go “hey, that is way cool!” And some others don’t. And some say “Wha?” Tell me what you’re trying to do and I can give you examples of OOP. But don’t expect to learn it from a book.

The only real difference there seems to me to be the need to add the new branch in the loop, in the procedural program. The branching would be implicit under OOP. Apart from that, in both cases you must add some code to calculate the area of a circular room. In one you have to allow the room.shape specifier to have a value equivalent to “circular”, in the other you have to create a new circular room class, which actually sounds more complicated than the procedural approach.

You are right in that the differences between procedural programming and OOP are incremental. And you’re right that in a simplified example like I gave, the benefits of OOP are not that great.

I didn’t want to include any actual code in my previous post, since I was trying to explain the differences to what I presumed was a non-programmer. But your point requires that we get into a bit of code.

To implement this room stuff, let’s say before the circular room has come along, in something like straight C, you’d probably make a struct to hold the room info, maybe something like this (forgive me if the syntax isn’t exactly right, it’s been a while since I’ve done C):



struct {
    int roomType;
    int width;
    int length;
} room;

A lazy programmer (like me) would be tempted to just use that, since both room types need two ints for the dimensions, even though the names aren’t exactly right for both. And then the building’s loop to calculate the total area would be something like:



for (int idx = 0; idx < numberOfRooms; idx++) {
    if (rooms[idx].roomType == RECTANGULAR_ROOM) {
        totalArea += rooms[idx].width * rooms[idx].height;
    } else {
        totalArea += (rooms[idx].width * rooms[idx].height) / 2;
    }
}


Ok, now we need to add the circular room. Hmm, what to do in that struct? A circular room needs just one dimension, the radius. I could just decide that for a circular room, the “width” variable will be used for the radius, but even as lazy as I am, that doesn’t sit right. I could just add another variable called “radius”, but that means that for rectangular and triangular rooms, I’m wasting the space for that unused radius variable, and for circular rooms I’m wasting the space for the width and length. So ok, I’ll use a union, and that means I can also make a clearer distinction between the rectangular and triangular rooms:



struct {
    int roomType;
    union {
        struct {
            int width;
            int length;
        } rectangularRoom;
        struct {
            int base;
            int height;
        } triangularRoom;
        struct {
            int radius;
        } circularRoom;
} room;


And now we need to change the loop to something like:



for (int idx = 0; idx < numberOfRooms; idx++) {
    if (rooms[idx].roomType == RECTANGULAR_ROOM) {
        totalArea += rooms[idx].rectangularRoom.width * rooms[idx].rectangularRoom.height;
    } else (rooms[idx].roomType == TRIANGULAR_ROOM {
        totalArea += (rooms[idx].triangularRoom.base* rooms[idx].triangularRoom.height) / 2;
    } else {
        totalArea += (rooms[idx].circularRoom.radius ^ 2) * PI;
    }
}


That’s not so horrible or time-consuming or hard to do. But notice that, number one, we’re still wasting the storage space of one int for every circular room. Not a biggy, but still a waste. Also notice that the code in that loop is getting somewhat crowded, what with all that dereferencing.

Now, in Java, we’d do something like this (I’m simplifying and leaving out things like constructors in order to focus on the pertinent parts of the code):



abstract class Room {
    int getArea();
}

class RectangularRoom extends Room {
    private int width;
    private in length;

    int getArea() {
        return width * length;
    }
}

class TriangularRoom extends Room {
    private int base;
    private in height;

    int getArea() {
        return (base* height) / 2;
    }
}


And then in the Building:



for (int idx = 0; idx < rooms.length; idx++) {
    totalArea += rooms[idx].getArea();
}


Now, to add a circular room, we make just one change, adding this class:



class CircularRoom extends Room {
    private int radius;

    int getArea() {

        return Math.square(radius) * PI;
    }
}


And we’re done. No changes need to be made to the Building class at all; that loop that calculates the total area remains as simple as ever.

Now, imagine that you’re dealing with something much more complicated than a building with rooms. Suppose you have twelve different types of things and each has twenty attributes. And now you need to add a thirteenth type of thing. And later, each of those thirteen things needs to have a new attribute. In a procedural program, how many structs and loops are you now going to have to change, compared to the OO program where you add one class, and add one method to each existing class.

It may seem like the amount of work in both programs is similar, and in some cases it is. But it should also be clear that the chances for making some sort of programming error in the procedural program are far higher than in the OO program, and the task of finding the error would also be harder. And finally, that in a procedural program it’s a bit easier for the lazy programmer to write something that will be harder for the next guy to read and know what’s going on in the code. OOP makes it incrementally more difficult for the lazy programmer to write crap.

I’m curious, sassyfras. Now that you have gotten over 24 hours’ worth of answers without adding any further posts of your own, are you getting any answers that actually help you?

I’m with Voyager.

If sassyfras couldn’t grasp Object Oriented Programming out of his book, the explanations provided here will not help him.

It’s important when explaining new concepts to people that you do not rely on any word or phrase that the learner may not be familiar with.

Hence, providing a definition of object oriented programming, and then loading your definition with words like “subroutine, struct, polymorphism, abstraction, child buckets, parent buckets, class, subclass…” etc etc, is very likely going to leave poor sassyfras all at sea.

Incidentally, this reminded me of the time I wanted to have a better understanding of what exactly it means when matter (as in physics) has charge.

I consulted wikipedia. Is there really any person alive who doesn’t understand what a charge is, but can understand this explanation? Here’s how wikipedia educates us all on what charge is:

So I hope that clears up to everyone what “charge” means.

As a scientist I have no idea what charge is, I just know what it does and how to mathematically describe it in terms of other variables.

You know, looking over the wikipedia article it is SURPRISINGLY well done in this case, and pretty simple due to its layman examples of the terms.

Chiming in with something a bit different from the usual definitions. This is a passage in a science fiction novel - ‘Starworld’ by Harry Harrison, and as a programmer who has some knowledge of OOP, I immediately felt that the character was describing it despite not using that term - or any of the usual buzzwords associated with it. How much it would explain to a nonprogrammer I’m not sure, but:

A bit basic when it comes to the programming, but the idea is there I think.

A friend’s father was a high school physics teacher, and his class gave him a book of is sayings. One I remember is:

“This is a door. This is a window. We’re not going to learn much physics this year.”

When I was in grad school, about 1976, I took a seminar class where we defined an object oriented language. We ran into lots of problems. The solutions to those problems is the complexity that we see described here. They are necessary, but not fundamental to the concept.

Thank you, sir Roadfood !
A fine, helpful answer.

Some of the other posts were so full of jargon that they sound like a philosophy professor discussing Hegelian metaphysics.

I too am looking forward to seeing how well sassyfras has assimilated all the information with which he has been presented in this thread. A simple UML presentation would suffice to demonstrate his new mastery of the subject.

Thanks, I was beginning to think that I’d gone overboard and the post was so long everyone just skipped it.

Wow.

Thank you. I’ve never ‘gotten’ this concept before either. GREAT post. :slight_smile: