Encapsulation, Information Hiding, and Access Modifiers
Abstraction involves reducing a real world entity to its essential defining characteristics. It helps to determine which attributes are essential to model the problem at hand, and also helps to determine what behaviors must be associated with those attributes. However, it doesn’t tell us how this will be implemented. Encapsulation extends the idea of abstraction by also modeling and linking the functionality of that entity. It deals with the issue of how to best modularize the features of a system into classes, which in turn are modularized into methods and attributes.
Encapsulation is basically a design issue that deals with how functionality is compartmentalized within a system. You shouldn’t
be required to know how something is implemented in order to be able to use it. The implication of encapsulation is that you can build anything any way you want, and then
the implementation can later be changed and it won’t affect other components within the system,
provided that the interface to that component does not change.
Definition
Encapsulation is the act of grouping into a single object both data and the operations that affect that data.
Encapsulation links the data to the operations that can be performed upon the data, and hence insures that data is only used in an appropriate manner. In effect, encapsulation places a boundary around an object's properties and methods.
In object-oriented programming, encapsulation is the inclusion within a program object of all the resources needed for the object to function - basically, related data and the methods that manipulate those data. The collective term for data items and methods bundled together with access restrictions is a class. Each class is a new data type.
Classes are useful for the following reasons:
Classes can be used to model real world entities, thereby permitting object-oriented languages to model a wide range of problems.
Bundling data and functionality together produces self-contained units which are more maintainable, reusable and deployable.
By enforcing the idea of encapsulation, object-oriented languages make it more difficult for the programmer to produce ‘bad’ code. Encapsulation allows an object-oriented language to enforce the integrity of a type (i.e., to make sure data is used in an appropriate manner) by preventing programmers from accessing data in a non-intended manner (e.g. asking if an Integer is true or false, etc.). Through encapsulation, only a predetermined group of functions can access the data.
Consider a clsStudent class. An object is an instance of the class, for example testStudent. Within the object there are instance variables such as studentID, major, and GPA. When a method operates on an object it may change the instance variables for that object. If the changeMajor method is called for the object testStudent, then the instance variable major that belongs to testStudent would be altered accordingly.
Purposes
When encapsulation is used properly, you can change an object's implementation without worrying that any other object can see and therefore depend on, the implementation details.
Objects in most object-oriented programming languages are encapsulated modules whose external interface consists of a set of operations that can access or change the values of the instance variables.
The object is said to "publish its interfaces." Other objects adhere to these interfaces to use the object without having to be concerned with how the object accomplishes it. Thus, the external interface of a module serves as a contract between the module and its clients, and by extension between the designer of the module and other designers. If clients depend only on the external interface, the module can be reimplemented without affecting any clients, so long as the new implementation supports the same (or an upward compatible) external interface. Thus, the effects of changes can be confined and interdependencies among separately-written modules are minimized.
There is a distinction between the interface and the implementation of a class because it makes programs easier to maintain. The implementation of a class may change, but as long as the interface remains the same, these changes do not require changes to any other classes that may use the class. This isolation of data makes it much easier to change one part of a program without causing problems to cascade into other parts of the program. This facilitates program evolution and maintenance.
These benefits are especially important for large systems and long-term data. To maximize the advantages of encapsulation, one should minimize the exposure of implementation details in external interfaces. A programming language supports encapsulation to the degree that it allows minimal external interfaces to be defined and enforced.
Another benefit of encapsulation is that it allows the functions that manipulate the data of an object to be bound to the object. This eliminates the need to check to be sure thatdata are being manipulated by the appropriate set of functions
In
summary, encapsulation
is significant because
it
makes it easier to build objects that are very reliable and consistent
because they have complete control over their own attributes, and it
makes program maintenance and change much easier.
Transition
Encapsulation is intended to provide a “cover” or “coating” that hides the internal structure of the object from the environment outside. Other objects (and end users) are prevented from doing anything to the insides of the object. They cannot change the data or change the procedure in a method. Only the methods of the object can change its data, so no unexpected changes can be imposed on the object from the outside.
However, encapsulation alone does not prevent the data of an object from being manipulated by functions other than the methods bound to the object. Encapsulation is merely the grouping of attributes and methods in a single structure. Clearly, encapsulation is not enough. Data must be protected in such a way that only the object itself can make such changes through its own behavior. Protecting data from manipulation by entities outside the object can be achieved by requiring that access to data be restricted to the services of the object that contains the data.
Therefore, realization of encapsulation requires information hiding.
Information
Hiding
Information
hiding is the technique of concealing implementation details within the
objects themselves, while the interface remains visible. Information hiding requires the
visibility of data to be restricted to within the (encapsulated) module. Data
is concealed within a class, so that it cannot be accessed mistakenly by
functions outside the class. Access
to data within an object is restricted to only those methods defined by the
object's class.
An object must be directed to change its own data with a message, because outside processes are prohibited from altering the nature of the object.
The object defines what services are available to other objects and prevents other objects from access or knowledge of the data and how a service is implemented.
Although objects may know how to communicate with each other, they normally are not allowed to know how other objects are implemented.
In order to support good design, we want to restrict access to data attributes and some methods.
The integral concept is that if one class wants information about another class, it should have to ask for it instead of just taking it. By restricting access to attributes, we prevent programmers from writing highly coupled code. [When code is highly coupled, a change in one part of the code
can cascade throughout the program.]
Information hiding is important because it allows an object complete control over the integrity of the data
contained within it. This gives us high cohesion and low coupling concerning the manipulation of data.
Information
hiding is accomplished through the use of the Private access modifier.
The
public and private keywords are called access modifiers, and they are used to control access to a class's instance variables and methods.Every instance variable or method definition should be explicitly preceded by a member access modifier.
public
private
Guidelines
Controlling Access to Data
Access to private data should be carefully controlled by the class's methods.
For example, to allow clients to read the value of private data, the class can provide a public "get" method (also called an accessor or query method).
To enable clients to modify private data, the class can provide a "set" method (also called a mutator method).
Private Methods
Some methods can be
private and serve as utility methods to the other methods of the class.A utility method is not part of a class's
public interface, but is a private method that supports the operation of the class's public methods.Utility methods are not intended to be called by clients of a class.
Encapsulation ≠ Information Hiding
Sometimes, encapsulation is given the same definition as information hiding.
It is important to note that information hiding is not the same as encapsulation.
The ability to protect or hide
methods or data makes it possible to encapsulate an object. Therefore,
encapsulation is the proper
use of protection and information hiding.
At the implementation level, code and data can be encapsulated together into a class (i.e., gathered together
in a code module) yet remain visible to other classes. In other words, encapsulation does not
guarantee information hiding.
If encapsulation was the same thing as information hiding, then one might make the argument that everything that was encapsulated was also
hidden. This is obviously not true. Unless instance variables are declared as
Private they may be encapsulated, but they are not hidden.
Similarly, information hiding does not necessitate encapsulation. Just because you protect or
hide methods or data does not mean you are encapsulating an object. If information hiding
is used (incorrectly) to hide members that belong in the public interface, then information hiding
exists without
encapsulating the class.
Summary
Here is
a set of guidelines from "Encapsulation
is not information hiding" by Wm. Paul Rogers.
Encapsulation rule 1: Place data and the operations that perform on that data in the same class.
This standard practice creates classes that adhere to the principles of abstract data types.
But you want more of your objects; you want them to represent cohesive, workable entities. A second rule concerns the manner of choosing the data and operations to encapsulate:
Encapsulation rule 2: Use responsibility-driven design to determine the grouping of data and operations into
classes.
This second encapsulation rule actually pertains to information hiding as well: don't just bundle data and operations together; let design principles guide you. Ask yourself what actions an object of the class will be responsible for. Don't let the class encapsulate more or less than a comprehensive set of reasonable responsibilities.
The principle of information hiding stipulates that you shield an object's clients from the internal design decisions made for that class of objects. So as a first rule for information hiding:
Information hiding rule 1: Don't expose data items. Make all data items private and use
accessor and mutator methods.
Don't fool yourself into believing no harm will result from directly accessing an object's internal data items.
Even if only you code against those internals, future vulnerability still exists.
Go one step further when hiding design decisions concerning internal data. When possible, don't even reveal whether an attribute is stored or derived. Client objects don't need to know the difference. An attribute is a quality or characteristic inherent in a class of objects. From the client's perspective, object attributes correspond to responsibilities, not internal data structure. That brings us to the next rule:
Information hiding rule 2: Don't expose the difference between stored data and derived data.
For example, a client object only needs to know that an object has an attribute of speed. Use an accessor method named speed() or getSpeed() rather than calculateSpeed(). Whether the value is stored or derived is a design decision best kept hidden.
The next rule concerns the choice of internal structure:
Information hiding rule 3: Don't expose a class's internal structure.
Clients should remain isolated from the design decisions driving the selection of internal class structure. For example, a client should not know whether an
array or a linked list is used to implement clsStack. Internal structure is particularly apparent through the use of method names like popTopArrayElement().
The final rule concerns choices of implementation details:
Information hiding rule 4: Don't expose implementation details of a class.
Don't allow clients to know or invisibly affect a class's implementation details. For example, a client should not be able to alter an internal calculation's result by changing the state of objects used in that supposedly hidden calculation.
Though not an exhaustive list, those rules help separate the concept of encapsulation provided by the language from the information hiding provided by design decisions.
Message passing is a way of communicating between objects.
Each class must be programmed to send and/or receive the appropriate messages.
The use of the term message emphasizes that objects are discrete entities and that we communicate with them by calling their member functions.
Satzinger and Orvik describe message passing as follows:
Another key concept in the object-oriented approach is message sending. When we interact with an object, we send messages to objects, and objects send messages to us (and to each other). Information hiding prevents the end users from changing an object’s data; however, the end user can ask the object to invoke, or perform, a method, and the method might change the object’s data. Therefore, when we ask an object to do something, we are sending a message to the object, asking it to invoke a method.
An object can also send a message to another object, invoking a method of some type. An object issuing a command to another object is really no different from an end user’s command.
On another level, a message might be thought of as an input or an output. When we ask a class of objects to create an object, we must supply the values for the attributes of the object. This is a message much like an input data flow. Similarly, when we ask an object to show us its attribute values or calculate some value for us, the object is producing an output data flow. So, if you think of messages as data flowing in and out of the object, the concept should seem familiar.
There is an important link between methods and messages. The message sent to an object must correspond to a method of the object. The complete message includes the object reference (the identity of the object), the method name, and the required data given to the object to be used by the method (the arguments). The method name and list of required arguments (signature) are what is needed to interact with the object.
Satzinger, John W. and Orvik, Tore V., The Object-Oriented Approach, Second Edition, Course Technology, 2001, pp. 44-45.
Notes compiled from several sources listed below:
A Primer on Object-Oriented Programming
Berard, Edward V., Abstraction, Encapsulation, and Information Hiding
Encapsulation
Encapsulation
Janssen,
Curtis L., Encapsulation, Sandia Labs, 1996
Java
Language Reference -- Chapter 5 -- Declarations
Morin, Randy Charles, OOP Concepts by Example, KBCafe.Com
Lee, Richard C.; Tepfenhart, William M., Practical Object-Oriented
Development With Uml and Java
Rogers,
Wm. Paul, "Encapsulation is not information hiding," JavaWorld, May 2001.
Satzinger,
John W. and Orvik, Tore V., The Object-Oriented Approach, Second Edition, Course
Technology, 2001, pp. 44-45.
searchNetworking.com
Definitions - encapsulation
Snyder,
A., Encapsulation and inheritance in object-oriented programming languages.
ACM SIGPLAN Notices, 21(11):38-45, Nov. 1986. OOPSLA '86 Conference Proceedings,
Norman Meyrowitz (editor), September 1986, Portland, Oregon.
Tutorial
3 -- Encapsulation
Please Report Errors in Notes Here