From your blog, it seems that you're familiar with both imperative and functional programming, and that you're familiar with the basic concepts involved in object-oriented programming, but you've just never really had it "click" as to what makes it useful. I'll try to explain in terms of that knowledge, and hope that it's helpful to you.
At its core, OOP is a way to use the imperative paradigm to better manage high degrees of complexity by creating "smart" data structures that model the problem domain. In a (standard procedural non-object-oriented) program, you've got two basic things: variables, and code that knows what to do with them. The code takes input from the user and various other sources, stores it in variables, operates on it, and produces output data which goes to the user or various other locations.
Object-oriented programming is a way to simplify your program by taking that basic pattern and repeating it on a smaller scale. Just like a program is a large collection of data with code that knows what to do with it, each object is a small piece of data bound to code that knows what to do with it.
By breaking down the problem domain into smaller pieces and making sure as much data as possible is bound directly to code that knows what to do with it, you make it a lot easier to reason about the process as a whole and also about the sub-issues that make up the process.
By grouping data into object classes, you can centralize code related to that data, making relevant code easier both to find and to debug. And by encapsulating the data behind access specifiers and only accessing it through methods, (or properties, if your language supports them,) you greatly reduce the potential for data corruption or the violation of invariants.
And by using inheritance and polymorphism, you can reuse preexisting classes, customizing them to fit your specific needs, without having to either modify the originals or rewrite everything from the ground up. (Which is a thing you should never do, if you can avoid it.) Just be careful you understand your base object, or you could end up with killer kangaroos.
To me, these are the fundamental principles of object-oriented programming: complexity management, code centralization and improved problem-domain modeling through the creation of object classes, inheritance and polymorphism, and increased safety without sacrificing power or control through the use of encapsulation and properties. I hope this helps you understand why so many programmers find it useful.
EDIT: In response to Joel's question in the comments,
Can you explain what an "object-oriented program" contains
(other than these fancy defintions you've outlined) that is fundamentally
different from an imperative program? How do you "get the ball rolling?"
A little disclaimer here. My model of "an object-oriented program" is basically the Delphi model, which is very similar to the C#/.NET model since they were created by former Delphi team members. What I'm saying here may not apply, or not apply as much, in other OO languages.
An object-oriented program is one in which all the logic is structured around objects. Of course this has to be bootstrapped somewhere. Your typical Delphi program contains initialization code that creates a singleton object called Application
. At the start of the program, it calls Application.Initialize
, then a call to Application.CreateForm
for every form you want to load into memory from the beginning, and then Application.Run,
which displays the main form on screen and starts up the input/event loop that forms the core of any interactive computer programs.
Application and your forms poll for incoming events from the OS and translate them into method calls on your object. One thing that's very common is the use of event handlers, or "delegates" in .NET-speak. An object has a method that says, "do X and Y, but also check to see if this particular event handler is assigned, and call it if it is." An event handler is a method pointer--a very simple closure that contains a reference to the method and a reference to the object instance--that's used to extend the behavior of objects. For example, if I have a button object on my form, I customize its behavior by attaching an OnClick event handler, which causes some other object to execute a method when the button is clicked.
So in an object-oriented program, most of the work gets done by defining objects with certain responsibilities and linking them together, either through method pointers or by one object directly calling a method defined in another object's public interface. (And now we're back to encapsulation.) This is an idea that I had no concept of back before I took OOP classes in college.