Data encapsulation is the most important concept to grasp when programming with objects. In object-oriented programming data encapsulation is concerned with:
- Combining data and how it's manipulated in one place. This is achieved through the state (the private fields) and the behaviors (the public methods) of an object.
- Only allowing the state of an object to be accessed and modified through behaviors. The values contained within an object's state can then be strictly controlled.
- Hiding the details of how the object works. The only part of the object that is accessible to the outside world is its behaviors. What happens inside those behaviors and how the state is stored is hidden from view.
Enforcing Data Encapsulation
Firstly, we must design our objects so that they have state and behaviors. We create private fields that hold the state and public methods that are the behaviors.[blockquote shade="no"]For example, if we design a person object we can create private fields to store a person's first name, last name, and address. The values of these three fields combine to make the object's state. We could also create a method called displayPersonDetails to display the values of the first name, last name and address to the screen.
Next, we must make behaviors that access and modify the state of the object. This can be accomplished in three ways:
- Constructor methods: A new instance of an object is created by calling a constructor method. Values can be passed to a constructor method to set the initial state of an object. There are two interesting things to note; one, Java does not insist that every object has a constructor method. If no method exists then the state of the object uses the default values of the private fields; two, more than one constructor method can exist. The methods will differ in terms of the values that are passed to them and how they set the initial state of the object.
- Accessor methods: For every private field we can create a public method that will return its value.
- Mutator methods: For every private field we can create a public method that will set its value. If you want a private field to be read only do not create a mutator method for it.
Lastly, we hide the implementation details of our object. As long as we stick to keeping the state fields private and the behaviors public there is no way for the outside world to know how the object works internally.
Reasons for Data Encapsulation
The main reasons for employing data encapsulation are:
- Keeping the state of an object legal. By forcing a private field of an object to be modified by using a public method, we can add code into the mutator or constructor methods to make sure the value is legal. For instance, imagine the person object also stores a username as part of its state. The username is used to log into the Java application we're building but is constrained to a length of ten characters. What we can do is add code into the username's mutator method that makes sure the username is not set to a value longer than ten characters.
- We can change the implementation of an object. As long as we keep the public methods the same we can change how the object works without breaking the code that uses it. The object is essentially a "black box" to the code that calls it.
- Re-use of objects. We can use the same objects in different applications because we have combined the data and how it's manipulated in one place.
- The independence of each object. If an object is incorrectly coded and causing errors it's easy to test and fix because the code is in one place. In fact, the object can be tested independently from the rest of the application. The same principle can be used in large projects where different programmers can be assigned the creation of different objects.