Encapsulation and access control

Figure 208. Access control: Overall objectives Slide presentation

Figure 209. Example: Implementing time and date Slide presentation
public class Time {
  private long  secondsSince_2000_01_01;

  public int getSecond() { 
    return
    (int) secondsSince_2000_01_01 % (60);
  }
  public int getMinute() {
    return (int)
      (secondsSince_2000_01_01 / 60) % 60;
  }
    ...
}
public class Time {
  private int second, minute,
         hour,day, month, year;

  public int getSecond() { 
        return second;
  }
  public int getMinute() { 
        return minute;
  }
    ...
}

Private attributes only accessible by methods belonging to class.

public items accessible also by alien classes.


Figure 210. Access violation Slide presentation

No access to private field of alien class Time:

public class Q {
  public static void main(String[] args) {

      Time t = new Time();

      // Error: 'secondsSince_2000_01_01' has private access in 'Time'
      t.secondsSince_2000_01_01 = 33445354L;
  }
}

Figure 211. Access rules Slide presentation
Access Level Other package Child class Same package Same class
public yes yes yes yes
protected no yes yes yes
Default no no yes yes
private no no no yes

  • Use the most restrictive access level that makes sense for a particular member.

  • Use private unless you have a good reason not to.

  • Avoid public fields except for constants. Public fields tend linking to a particular implementation and limit your flexibility in changing your code.


exercise No. 91

Understanding access control

Q:

Follow the example given in Classes and Packages of the Example Used to Illustrate Access Levels and define two respective classes Alpha and Beta in different packages. Supply suitable dummy methods and fields illustrating both legal and illegal access.

A:

Alpha Beta AlphaSub Gamma
package package_one;

public class Alpha {

  public     int attribPublic;
  protected  int attribProtected;
/*Default*/  int attribDefault;
  private    int attribPrivate;

  void dummy(/* same class */) {
    int v;
    v = attribPublic;
    v = attribProtected;
    v = attribDefault;
    v = attribPrivate;
  }
}
package package_one;

public class Beta {






  void dummy(Alpha a) {
    int v;
    v = a.attribPublic;
    v = a.attribProtected;
    v = a.attribDefault;
    v = a.attribPrivate;
  }
}
//different package
package package_two;

import package_one.Alpha;

public class AlphaSub
              extends Alpha {


  void dummy(/* Inherited */) {
    int v;
    v = attribPublic;
    v = attribProtected;
    v = attribDefault;
    v = attribPrivate;
  }
}
//different package
package package_two;
import package_one.Alpha;

public class Gamma {




  void dummy(Alpha a) {
    int v;
    v = a.attribPublic;
    v = a.attribProtected;
    v = a.attribDefault;
    v = a.attribPrivate;
  }
}

Note

Notice the related follow up inheritance exercise.

exercise No. 92

Explaining times

Q:

In Figure 209, “Example: Implementing time and date ” we have:

public int getMinute() {
    return
    (int) (secondsSince_2000_01_01 / 60) % 60;
}
  1. Explain the underlying idea of the term (secondsSince_2000_01_01 / 60) % 60.

  2. Explain the (int) cast's necessity. Why is there no overflow error about to happen?

A:

  1. Every 60 seconds a new minute begins and seconds start from zero again. Every 60 minutes a new hour will start and both seconds and minutes start from zero again.

    The term secondsSince_2000_01_01 / 60 amounts to the number of minutes passed since 2000/01/01. Building the remainder to 60 provides the current minute.

    Example: If there are 4450 seconds elapsed this amounts to 4450 / 3600 == 1 hour, (4450 / 60) % 60 == 14 minutes and 4450 % 60 == 10 seconds.

  2. The expression (secondsSince_2000_01_01 / 60) % 60 is of type long due to the presence of a long variable. However the % operator guarantees the result to be in the integer range 0 ... 59 which may thus be safely narrowed to an int value.