Java Encapsulation

0

What is encapsulation

Encapsulation is information hiding but what kind of information are we trying to hide? In object oriented world, class is the unit of abstraction and a class consists of data and behavior. The instance variables hold the data where as a method’s implementation add behavior to the class. We are trying to restrict the access to the data and the methods which work on the data.

Why do we need to encapsulate?

Suppose class A is dependent on B. If we have everything visible in B, whenever we change B (data or implementation), it is going to directly effect A.
This is a major design flaw as A’s evolution is dependent on B’s evolution. We should use encapsulation here to a degree that will allow us to change B’s implementation without affecting the calling code in A.
You can read more about this in my dependency injection article.

In Java, other than classes we also have interfaces. Interfaces don’t have implementation so programming to interface is one of the way of encapsulating implementation.
A well-designed module hides all of its implementation details, cleanly separating its API from its implementation using proper interfaces. Modules then communicate with one another only through their APIs and are oblivious to each others’ inner workings. This is called programming to interfaces.

For example:
Class H has a member variable of type IFeature2 where IFeature2 is an interface.

package javarticles.javainheritance;

public class H {
    private IFeature2 mFeature2;
    
    public void doSomething() {
        System.out.println("Call feature2");
        mFeature2.doFeature2();
    }
    
    public void setFeature2(IFeature2 mFeature2) {
        this.mFeature2 = mFeature2;
    }
}

IFeature2:

package javarticles.javainheritance;

public interface IFeature2 {
    public void doFeature2();
}

Since IFeature2 is an interface when we call mFeature2.doSomething(), we are making a call to an API and not to a specific implementation. This is programming to interface.
We can inject the implementation using a setter or through constructor. Below is an example where we inject different implementations through a setter.

    @Test
    public void callFeature2() {
        H h = new H();
        
        h.setFeature2(new G());        
        h.doSomething();
        
        h.setFeature2(new IFeature2() {
            
            @Override
            public void doFeature2() {
                System.out.println("Different feature2");
            }
        });
        h.doSomething();        
    }

Output:

Call feature2
 do feature2 in G
Call feature2
Different feature2

The same concept can be applied on each module so that each can communicate with other only through their APIs and are oblivious to each others’ inner workings. This concept is known as information hiding or encapsulation.

  • Encapsulation effectively decouples the modules that comprise a system, allowing them to be developed, tested, optimized, used, understood, and modified individually.
  • This speeds up system development because modules can be developed in parallel.
  • It eases the burden of maintenance because modules can be understood quickly and debugged with little fear of harming other modules.
  • Once a system is complete modules can be optimized without affecting the correctness of other modules.
  • Information hiding increases software reuse because individual modules do not depend on one another.
Share.

Leave A Reply