Witscale Test Center

11.1 Encapsulation and implementation hiding


11.1 Encapsulation and implementation hiding

The word encapsulate literally means “to enclose in” as if in a capsule. A Java class encapsulates its state and behavior. The state is encapsulated in member variables and behavior is encapsulated in methods. A good object-oriented practice suggests that state should not be readily accessible from outside class. Instead, you should tightly encapsulate it in such a way that it is accessible only through proper channels. Let us see what a proper access means with an example. Assume that you write a Java class Elephant with some state and some functionality. Say for instance,

 

public class Elephant {

  public String color;

   public int age;

   public void mudBath() {}

}

 

Note that the state of your class is represented by public variables. Since public variables can be accessed and modified by any class, other classes may exploit you class by modifying them incorrectly. For example, the Elephant class may be used by another class Zoo in an inappropriate way as:

 

class Zoo {

  public void addElephant() {

    Elephant bigElf = new Elephant();

    bigElf.color = "red";        // Improper use

    bigElf.age = -15; // Improper use

  }

}

 

The class Zoo is a client (user) of your class. But it is incorrectly using your class.  How can you ensure that your code is properly used by the user code? To start with, you need to restrict the access to all the member variables. You can declare them as private. Thus, the user classes of your class cannot change them appropriately. However, they need to access these variables anyway. Therefore, you must provide a proper access mechanism for the variables. The correct way is to write accessor methods for each of the member variables as:


Now if the user of Elephant class wants to access the member variables, it must do so via accessor methods. Thus you have encapsulated the member variables in protective shell inside the class. The user classes cannot access them directly. Figure 11.1 shows the difference encapsulation makes to your code.


Figure 11.1 Encapsulating (hiding) variables from the user classes

 

You have successfully hid the member variable age from outside world, therefore the user classes cannot directly access it to perform improper modifications. However, they can still send invalid values to the setter method. The advantage now is that you can put validity checks in setter method before actually setting the value as:

 

public void setAge(int age) {        

  if( age > 0 ) {                      // Validity check

    this.age = age;                 

  }

}

                         

Moreover if you further change the setAge() method, the code of the user classes need not change. For example, if you change the condition in setAge as (age >= 0), the class calling setAge() need not change. Thus the users of your code does not need to know how your state is stored, if they can access it.

 

A popular misconception about adding accessors for member variables is that it is inefficient and therefore you should not add accessors for variables but make them directly accessible. On the contrary, often the compiler optimizes accessor methods by inlining them. Thus calling them is almost as efficient as the directly accessing the variable.