Were the members of a data structure implementation before OOP left public?

2018-07-18 23:07:52

When a data structure (for example: a queue) is implemented using an OOP language, some members of the data structure needs to be private (for example: the number of items in the queue).

Now a queue can also be implemented in a procedural language using a struct and a group of functions that operate on the struct.

But in a procedural language you can't make the members of a struct private. So were the members of a data structure implementation in a procedural language left public, or were there some trick to make them private?

First, being procedural versus object oriented has nothing to do with public vs private. Plenty of object oriented languages have no notion of access control.

Secondly, in "C" - which most people would call procedural, and not object oriented, there are lots of tricks you can use to effectively make things private. A very common one is to use opaque (e.g. void*) pointers. Or - you can forward declare an object, and just not define it in a h

  • First, being procedural versus object oriented has nothing to do with public vs private. Plenty of object oriented languages have no notion of access control.

    Secondly, in "C" - which most people would call procedural, and not object oriented, there are lots of tricks you can use to effectively make things private. A very common one is to use opaque (e.g. void*) pointers. Or - you can forward declare an object, and just not define it in a header file.

    foo.h:

    struct queue;

    struct queue* makeQueue();

    void add2Queue(struct queue* q, int value);

    ...

    foo.c:

    struct queue {

    int* head;

    int* head;

    };

    struct queue* makeQueue() { .... }

    void add2Queue(struct queue* q, int value) { ... }

    Look at the windows SDK! It uses HANDLE and UINT_PTR, and things like that to be generic handles to memory used in APIs - effectively making the implementations private.

    2018-07-18 23:31:17
  • OOP did not invent encapsulation and is not synonymous with encapsulation. Many OOP languages do not have C++/Java style access modifiers. Many non-OOP languages have various techniques available to offer encapsulation.

    One classic approach for encapsulation is closures, as used in functional programming. This is significantly older than OOP but is in a way equivalent. E.g. in JavaScript we might create an object like this:

    function Adder(x) {

    this.add = function add(y) {

    return x + y;

    }

    }

    var plus2 = new Adder(2);

    plus2.add(7); //=> 9

    The above plus2 object has no member that would allow direct access to x – it's entirely encapsulated. The add() method is a closure over the x variable.

    The C language supports some kinds of encapsulation through its header file mechanism, particularly the opaque pointer technique. In C, it is possible to declare a struct name without defining its members. At that point no variable of the type of that struct can be used, but we can use

    2018-07-18 23:50:37
  • Note there are many OO languages without a built-in ability to mark members private. This can be done by convention, without a need for the compiler to enforce privacy. For example, people will often prefix private variables with an underscore.

    There are techniques to make it harder to access "private" variables, the most common being the PIMPL idiom. This puts your private variables in a separate struct, with just a pointer allocated in your public header files. This means an extra dereference and a cast to get any private variables, something like ((private_impl)(obj->private))->actual_value, which gets annoying, so in practice is rarely used.

    2018-07-18 23:59:53