Encapsulation: Private, Public, Friendly, and Protected

It is often desirable to hide certain aspects of a class from public view: one may not want to bother a user with unnecessary details, or one would like to prevent unauthorized access to data. To prevent this from happening, a process called ‘data encapsulation’ is used:

 Encapsulation using Private, Public, Friendly, or Protected

Encapsulation is the process of allowing or disallowing access to a class or to members of a class. Java provides several modifiers to facilitate encapsulation:

public: a field, method, or class that is accessible to every class
protected: a field, method, or class that is accessible to the class itself, subclasses, and all classes in the same package or directory.
friendly: a field, method, or class that is accessible to the class itself and to all classes in the same package or directory. Note that friendly is not a separate keyword. A field or method is declared friendly by virtue of the absence of any other access modifiers.
private: a field or method that is accessible only to the class in which it is defined. Note that a class can not be declared private as a whole.

We will usually deal with small to medium sized projects where all classes reside in the same directory. Hence, for those classes there is little difference between friendly and protected; the modifiers public and private will be the more useful ones for us.

Example:

Write a class containing a private, public, and friendly field. Then try to access these fields from another class.

We need to write two classes: one class with various fields, and a second class to attempt to access these fields. Here is an example:

class AccessTest
{  // fields
   private int privateNum = 1;
   public int publicNum = 3;
   int friendlyNum = 4;
}
class Tester
{  // methods
   public static void main(String args[])
   {
      AccessTest a = new AccessTest();
      System.out.println(a.privateNum);
      System.out.println(a.friendlyNum);
      System.out.println(a.publicNum);
   }
}

When trying to compile the class Tester, Java will print the following error message:

C:\PROGS\JAVA\OOP\INTRO>javac Tester.java
Tester.java:13: Variable privateNum in class AccessTest not accessible from class Tester.

That is because the class Tester can not access the private field in the AccessTest class. If the offending line is removed from the Tester class, everything will compile fine, and the output would be the numbers 3 and 4.

The above definition of private leads to an interesting question: if a class declares a field to be private, and two objects of the same class exist, can they access each other’s private fields? That situation rarely happens, and will be skipped. Refer to a book on Java for details. Similarly, one could construct another technical examples to highlight the differences between protected and friendly. However, in most of our projects we will be content with using private and public access, and therefore we will focus on those modifiers.

To help with deciding when to use which access modifier, here is a rule of thumb.

Definition: Rule of Thumb - Public or Private

Methods and fields should be declared private if outside access could put an object in an undefined or invalid state. As a rule of thumb, all fields of an object should be declared private if possible.

Methods and fields should only be declared public when unauthorized access can not produce any undesired results. At least one method of a class should be non-private.

If a class is declared public, the name of the class must be identical with the name of the file for the source code of the class, with the extension .java appended.. Public classes can be (re)compiled automatically by the Java compiler as needed.

Constructors and destructors should never be declared private by virtue of what they try to accomplish. Private and public are the most common access modifiers used, while friendly access (i.e. no modifier keyword) is frequently used to allow for inheritance of fields without allowing global access.

 Example:

In our previous class Rectangle we did not use any access modifiers. Hence, all fields and methods are implicitly declared friendly. Redefine our Rectangle class using the appropriate access modifiers and our above rule of thumb.

We do not need to change the implementation of our methods. We simply change the field declarations and method headers as follows, according to our rule of thumb:

public class Rectangle
{  // fields 
   private String name; 
   private double area;
   private double perimeter;
   private double width;
   private double height;
   // constructor 
   public Rectangle()
   // methods 
   public void setDimenions(double _width, double _height)
   public void computeArea();
   public void computePerimeter(); 
   public void display()
}

Note that the private fields width and height can not be accessed directly any more, but the public method setDimensions, in turn, can access those fields. That method can act as a kind of filter, if necessary, preventing a user from destroying the integrity of the class. In fact, such methods happen frequently.

Definition: Set and Get methods

Set and get methods provide controlled access to data fields of a class, acting as a filter between the user of the class and any internal requirements that our class needs to maintain. Set and get methods are appropriate for non-public fields, and they should not be declared private. There is no standard keyword for these methods, but the usual convention is to construct the method name using the appropriate private field name and prefacing it with the words set or get. Not every private data field needs set and/or get methods.

Frequently, classes may also have private methods in addition to private fields. Those would be only of use for the internal workings of the class, and should not be made public either to shield the user from any unnecessary complexities, or to maintain, as before, the integrity of the class. Such private methods are frequently called utility methods.

Definition: Utility Method

A utility method is a private method of a class. The user of the class does not need to know about the existence of it, but it is needed by the class itself to perform its required tasks and implement its public methods.

We will later see many examples of set and get methods, as well as plenty of utility methods.

(bgw)