Encapsulation allows you to make internal changes to a class without affecting any code that calls the class. This reduces coupling, or how much any given class relies on the implementation of another class.
For example, let's change the implementation of the Angle class from the previous example:
public class Angle {
private double angleInDegrees;
public static Angle angleFromDegrees(double degrees){
Angle a = new Angle();
a.angleInDegrees = degrees;
return a;
}
public static Angle angleFromRadians(double radians){
Angle a = new Angle();
a.angleInDegrees = radians*180/Math.PI;
return a;
}
public double getDegrees(){
return angleInDegrees;
}
public double getRadians(){
return angleInDegrees*Math.PI / 180;
}
public void setDegrees(double degrees){
this.angleInDegrees = degrees;
}
public void setRadians(double radians){
this.angleInDegrees = radians*180/Math.PI;
}
private Angle(){}
}
The implementation of this class has changed so that it only stores one representation of the angle and calculates the other angle when needed.
However, the implementation changed, but the interface didn't. If a calling class relied on accessing the angleInRadians method, it would need to be changed to use the new version of Angle
. Calling classes shouldn't care about the internal representation of a class.