Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I studied computer science near the end of 1980s, and wasn't taught OOP that formally.

With Pascal or C, when I understand the top-down design of functions, and the idea of black box, then everything just seem to make sense, as if there is a "oh I get it!" -- some kind of totally getting it and enlightenment feeling.

But with OOP, all I know was the mechanics: the class, instance, method, inheritance, polymorphism, encapsulation. It was like, I knew all the "this is how it is", but never had the feeling of "I totally get it", the enlightened feeling.

Would somebody be able to describe it, or point to a chapter in some book or paper which talks about OOP so that the reader can feel: "I totally get it!" on OOP?

share|improve this question

closed as not a real question by Michael K, Jarrod Roberson, World Engineer, Robert Harvey, gnat Apr 12 '12 at 20:12

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

2  
This question is probably too vague to last long, so I'll just comment: in a nutshell, OOP's value isn't always evident while writing software - but it becomes VERY evident when you need to MAINTAIN software over a long period of time, especially if multiple people are developing/maintaining. In some languages, the principle of encapsulation creates compiler-enforced restrictions on how much a single change ran ripple throughout the code-base, and polymorphism allows for easy modularity. You can achieve similar results with procedural, but I suppose OOP encourages these things more. –  Charles Salvia Apr 12 '12 at 18:38
    
my question is to understand OOP very well... would you be able to think of a way of asking so that it is not a vague question... –  動靜能量 Apr 12 '12 at 18:55
    
it's just a way to break dependency chains and make them terminate at an interface. Make a class that has no other dependencies than interface classes; then add some reference data members to it, and it'll work. –  tp1 Apr 12 '12 at 19:11
add comment

3 Answers

Do you already understand the principle of Object Based programming? Many people may tell you that they are one and the same thing, but really Object Oriented programming is an extension of the former.

In the world of procedural programming, things are pretty much broken down between data structures and behaviour (functions/procedures); your functions/procedures stand alone, and perform operations on your data.

e.g. a classic linked list header might look like

struct node { /* */ };

void add_to_list( node* head, data d );
void remove_from_list( node* head, data d );
data* find_in_list( node* head, data d );
void sort_list( node* head );

There's a straightforward pattern between each of those functions - their first argument always references the linked list structure in some way; The calling-convention will always look something like

node* head = create_node( 1 );
add_to_list( head, 2 );
add_to_list( head, 3 );
remove_from_list( head, 2 );
data* d = find_in_list( head, 1 );
sort_list( head );

In the world of object-based programming, the relationship between the data structure and the behaviour which operates on the data is acknowledged, then tightly bound together in the form of data structures which have both data and behaviour (a.k.a classes). The difference between object-based programming and procedural programming is extremely simple - it is nothing more than a different way to organise your code into logical units.

class linked_list 
{     
    void add( data d );
    void remove( data d );
    data* find( data d );
    void sort();
}

Compare that to the procedural solution - the main differences are

1) the functions exist inside a data structure

2) The functions no longer reference to the data structure in their arguments - because a reference to a data structure Object is implied by the way the function is used and the object is called, using the new calling convention...

linked_list my_list;
my_list.add( 2 );
my_list.add( 3 ); 
my_list.remove( 2 );
data* d = my_list.find( 1 );
my_list.sort();

Hardly revolutionary from a pure code point of view; but looking more closely at it, the code is now a little bit more organised. Not only this, there's no longer a concept of a 'head' floating around the main bit of code where the list is actually used!. The head is an implementation detail of the linked list. In the procedural solution, the head is wide open for all to see, and there's nothing stopping a rogue bit of code from breaking the list. Furthermore, programming languages which support classes tend to also help you isolate the memory management - with any luck, any heap-management is entirely self-contained within the depths of the class instead of in standalone functions.

Furthermore, the real benefit of approaching programming in this way is the benefit for the person designing it; You can "think bigger" than simply juggling characters, integers, arrays, structures, pointers, handles, etc;

Stepping away from the linked list example, think of GUI code - instead of worrying about API calls, resource lifetimes, callbacks, handles, etc, you can design code which says "First I'll create a Dialogue Box, then I'll add a button, then I'll link this button to a function/event".

Given the ability to create classes which represent real-world entities, you can write the code in a manner which fits far more closely to your problem domain; selectively ignoring all of the nitty-gritty-details, and working at a high level where concerns about precisely how a Window/Form/Button/Tickbox/etc functions is a problem to be solved elsewhere. There are a bunch of software-design principles associated with this kind of thing, but the main ones are Encapsulation and Separation of Concerns.

--

Note - this far I've only mentioned Object-Based programming; Object-Oriented programming takes it one step further, Although in my personal opinion, "Object Orientated Programming" (OOP) is perhaps the most widely-used and poorly-name software development concept ever uttered. (Others feel free to disagree, that's just my take on it)

  • The real power and purpose of Object Oriented Programming has nothing (IMHO) to do with Objects and is not specifically about Programming. To my mind, "OOP" is about Designing to an interface (Maybe Interface Oriented Design would be a better name?)

The thing which separates "OOP" from Object-based programming is called Inheritance - it is the ability to specify a general-purpose class which is reused by other specialised classes.

going back to the linked list example - look at the functions

    void add( data d );
    void remove( data d );
    data* find( data d );
    void sort();

They belong to a linked list, but in fact, they should also be applicable to an array, a binary tree, a hashmap...

Suppose you have 4 different classes for each kind of data structure - you want to write a find-and-replace function which stands on its own and simply looks like

data* item = structure.find( something );
if ( item != NULL )
{
    *data = replacement;
    return true;
}
else
{
    return false;
}

I guess it could be a standalone function, what does the signature for the function look like though? That logic applies to any structure which has a find(data) member, but if all you've got are a bunch of different data types, then you might end up doing something like

bool replace(void* structure, int structure_type, data something, data replacement)
{
    if( structure_type == eLINKEDLIST ) // etc.
    else if( structure_type == eARRAY ) // etc.
    else if( structure_type == eBINARYTREE ) // etc.

Yuck, yuck, and more yuck! the code suffers from else-if-heimers disease (Where's the hashmap? Oops!) and looks like a dumping ground for special-case stuff. Furthermore, there might be a bunch of other identical chunks of code lying around im similar functions.

Inheritance to the rescue maybe? Well, a void* is unpleasant - it would be nice to be able to simply pass in a reference to a data type which simply provides access to the find function of any kind of data structure. Who cares whether its a linked list, an array, a hashmap. Most importantly, any code which uses too much if-else-if-else-if is usually a careless mistake waiting to happen

class interface_structure
{     
    virtual void add( data d );
    virtual void remove( data d );
    virtual data* find( data d );
    virtual void sort();
}

Then all which is left to do is define each of the other structures

class linked_list : public interface_structure;
class hashmap : public interface_structure;
class array : public interface_structure;
class binary_tree : public interface_structure;

Now there's an obvious way to write the replace function. No need to figure out what the kind of structure is - replace() simply couldn't care, because it has been designed by way of selective ignorance:

bool replace( interface_structure* structure, data something, data replacement )
{
    data* item = structure.find( something );
    if ( item != NULL )
    {
        *data = replacement;
        return true;
    }
    else
    {
        return false;
    }
}

In fact, the replace function could possibly also be part of the interface structure (Which would turn the interface structure into an Abstract Base Class - that's a design choice which a programmer would be faced with. Standalone functions are not necessarily a bad thing).

As I hinted before, I don't believe the power here is necessarily in the programming - it's all in the design. "Object Oriented Programming" is a complete paradigm shift which requires that you re-learn how to approach problem solving all over again. You need to make the mental shift which ignores implementation detail and examines a program's behaviour at the higher level.

Designing OO code is all about identifying themes and commonalities across different "kinds of" entities; making the shift isn't something which happens straight away or naturally, but I believe you need to learn to "think" OO before you can program it. (But of course the programming practice is generally where the learning happens)

(There's a lot more to "Object based" and "Object Oriented" design/programming than this.. design patterns, S.O.L.I.D principles, and a whole bunch of other things. )

share|improve this answer
add comment

Top-down, structured programming tends to focus on actions -- verbs you'd use in describing the program. The data used/produced by those actions tends to be treated as secondary at best.

OOP focuses much more on the "things" in the program -- nouns you'd use in describing the program. This thing (object) over here talks to that thing (another object) over there. Data is placed on a much more even footing with the actions. More importantly, rather than segregating all the data into one set and all the code into another, it encourages thinking in terms of putting specific data together with the code that works on that data.

Rather than segregating between data and code, segregation is based more on functionality -- all the code and data related to one thing become an object. The code and data related to something else become another object.

share|improve this answer
add comment

OOP is basically the same principle. Except now the black box can also contain data (member variables) and can be chosen at run-time through inheritance.

Of course, those things are very important. But conceptually, they're quite simple.

share|improve this answer
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.