Search code examples
oopterminologyencapsulation

Meaning of encapsulation


What is the meaning of encapsulation ?


Solution

  • Encapsulation is a moderately easy concept once you realise it (probably) comes from the same base word as capsule.

    It's simply a containment of information.

    Encapsulation means that a class publishes only what is needed for others to use it, and no more. This is called information hiding and it means classes can totally change their internals without having an effect on any of their users.

    In other words, a dictionary class can begin life as a simple array and progress to a binary tree of words then even maybe to some database access functions, all without changing the interface to it.

    In an object oriented world, objects hold both their data and the methods used to manipulate data and that is the pinnacle of encapsulation. One way this is done is to make sure each object knows which functions to call to manipulate its data, and ensure the correct ones are called.

    As an example, here's a class for maintaining integer lists in my mythical, but strangely Python-like and therefore hopefully easy to understand, language:

    class intlist:
        private int val[10]    # Slots for storing numbers.
        private bool used[10]  # Whether slot is used or not.
    
        public constructor:
            # Mark all slots unused.
    
            for i in 0..9:
                used[i] = false
    
        public function add(int v) throws out-of-memory:
             # Check each slot.
    
            for i in 0..9:
                # If unused, store value, mark used, return.
    
                if not used[i]:
                    used[i] = true
                    val[i] = v
                    return
    
            # No free slots, so throw exception.
    
            throw out-of-memory
    
        public function del(int v) throws bad-value:
             # Check each slot.
    
            for i in 0..9:
                # If slot used and contains value.
    
                if used[i] and val[i] == v:
                    # Mark unused and return.
    
                    used[i] = false
                    return
    
            # Value not found in any used slot, throw exception.
    
            throw bad-value
    
        public function has(int v):
             # Check each slot.
    
            for i in 0..9:
                # If slot used and contains value.
    
                if used[i] and val[i] == v:
                    return true
    
            # Value not found in any used slot.
    
            return false
    

    Now the only information published here are the constructor and three functions for adding, deleting, and checking for values (including what exceptions can be thrown).

    Callers need know nothing about the internal data structures being used (val and used), or the properties of the functions beyond their "signatures" (the content of the "function" lines).

    Because everything else is encapsulated, it can changed it at will without breaking the code that uses it.

    I could, for example, do any of the following:

    • make the arrays longer;
    • store the data sorted, or in a binary tree instead of an array to make it faster.
    • change the used array into a count array (initialised to zero) so that many occurrences of a single number use just the one slot, increasing the quantity of numbers that can be stored where there are duplicates.
    • store the numbers in a database, located on a ZX-80 retro-computer located in outback Australia, and powered by methane produced from kangaroo droppings (though you may notice a latency change).

    Basically, as long as the published API doesn't change, we am free to do whatever we want. In fact, we can also add things to the API without breaking other code, I just can't delete or change anything that users already rely on.


    You should note that encapsulation isn't something new with object orientation. It's been around for ages, even in C by ensuring that information is hidden within a module (usually a source file or group thereof with private headers).

    In fact, the stdio.h FILE* stuff is a good example of this. You don't care what's actually behind the pointer since all the functions which use it know how to do their stuff.