Data Field Encapsulation

Paul Ngugi - Jun 3 - - Dev Community

Making data fields private protects data and makes the class easy to maintain. The data fields radius and numberOfObjects in the CircleWithStaticMembers class in CircleWithStaticMembers.java can be modified directly (e.g., c1.radius = 5 or CircleWithStaticMembers.numberOfObjects = 10). This is not a good practice—for two reasons:

  • First, data may be tampered with. For example, numberOfObjects is to count the number of objects created, but it may be mistakenly set to an arbitrary value (e.g., CircleWithStaticMembers.numberOfObjects = 10).
  • Second, the class becomes difficult to maintain and vulnerable to bugs. Suppose you want to modify the CircleWithStaticMembers class to ensure that the radius is nonnegative after other programs have already used the class. You have to change not only the CircleWithStaticMembers class but also the programs that use it, because the clients may have modified the radius directly (e.g., c1.radius = -5).

To prevent direct modifications of data fields, you should declare the data fields private, using the private modifier. This is known as data field encapsulation.

A private data field cannot be accessed by an object from outside the class that defines the private field. However, a client often needs to retrieve and modify a data field. To make a private data field accessible, provide a getter method to return its value. To enable a private data field to be updated, provide a setter method to set a new value. A getter method is also referred to as an accessor and a setter to a mutator.

A getter method has the following signature:

public returnType getPropertyName()

If the returnType is boolean, the getter method should be defined as follows by convention:

public boolean isPropertyName()

A setter method has the following signature:

public void setPropertyName(dataType propertyValue)

Let’s create a new circle class with a private data-field radius and its associated accessor and mutator methods. The class diagram is shown in Figure below.

Image description

The new circle class, named CircleWithPrivateDataFields, is defined in program below:

package demo;

public class CircleWithPrivateDataFields {
    /** The radius of the circle */
    private double radius = 1;

    /** The number of objects created */
    private static int numberOfObjects = 0;

    /** Construct a circle with radius */
    public CircleWithPrivateDataFields() {
        numberOfObjects++;
    }

    /** Construct a circle with a specified radius */
    public CircleWithPrivateDataFields(double newRadius) {
        radius = newRadius;
        numberOfObjects++;
    }

    /** return radius */
    public double getRadius() {
        return radius;
    }

    /** Set a new radius */
    public void setRadius(double newRadius) {
        radius = (newRadius >= 0) ? newRadius : 0;
    }

    /** return numberOfObjects */
    public static int getNumberOfObjects() {
        return numberOfObjects;
    }

    /** Return the area of this circle */
    public double getArea() {
        return radius * radius * Math.PI;
    }
}

Enter fullscreen mode Exit fullscreen mode

The getRadius() method (lines 22–24) returns the radius, and the setRadius(newRadius) method (line 27–29) sets a new radius for the object. If the new radius is negative, 0 is set as the radius for the object. Since these methods are the only ways to read and modify the radius, you have total control over how the radius property is accessed. If you have to change the implementation of these methods, you don’t need to change the client programs. This makes the class easy to maintain.

The program below gives a client program that uses the Circle class to create a Circle object and modifies the radius using the setRadius method.

Image description

The data field radius is declared private. Private data can be accessed only within their defining class, so you cannot use myCircle.radius in the client program. A compile error would occur if you attempted to access private data from a client.

Since numberOfObjects is private, it cannot be modified. This prevents tampering. For example, the user cannot set numberOfObjects to 100. The only way to make it 100 is to create 100 objects of the Circle class. Suppose you combined TestCircleWithPrivateDataFields and Circle into one class by moving the main method in TestCircleWithPrivateDataFields into Circle. To prevent data from being tampered with and to make the class easy to maintain, declare data fields private.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .