Data abstraction with conventional imperative languages, like C, lets us define operations such as insertion and deletion for lists within the body of a procedure and then to program without regard to how they are achieved internally. The definition of these operations is still separate from the definition of the structures to which they are applied, however. Nothing prevents accidental use with the wrong instance of a data structure, so that an array representing a first in first out queue could accidentally be used by the push operation intended for a similar array used to represent a stack.
Object based abstraction says that the definition of a data structure and of the operations upon it should be as a single unit. Thus a list is no longer an array plus a set of operations on that array and the values which it can store. Instead a list is an object with a state and a set of operations. The state tells us what the effect of each operation will currently be. The operations modify and report on the state of the object to which they belong. Only operations defined for a data type are allowed. Information hiding implements Parnas' rules for modularity in programs [1]. He said that:
Data abstraction and information hiding are the goals we wish to achieve. One approach would be to regard them as disciplines which should be followed in programming. Encapsulation says that they should be enforced by the language and forbids direct access to data within an object, from outside it, and to data outside an object, from within it. Most object oriented languages allow this to be enforced for both data (instance variables) and for private operations. Only those operations explicitly made visible should be accessible outside the object and all such operations should apply to a particular instance of an object type or class. Only data passed in as parameters should be allowed to enter an object from outside.