Encapsulation and packaging

When designing software it is important to distinguish between interaction with outside world, or clients who use software, and with internal interactions. This is similar to engineering a TV set. The TV set presents only a few buttons, the minimum amount of interface to conveniently use it. However there are many more connections inside the device, but these are only connected between internal parts.

Java provides three type modifiers to distinguish between internal and external usage: public, protected, and private.

Packages

In order to understand encapsulation in Java we need to look at packages. We have already used them when we write import java.util.*. This statement imports all classes within the package java.util.

A Java source file can declare which package the classes in the file belongs using a package keyword (see http://docs.oracle.com/javase/tutorial/java/package/packages.html for an overview). A package is a grouping of interrelated classes, interfaces, etc. One can define a hierarchy of packages using . notation as follows:

    package my.library;

    class Book {
        ...
    }

Once compiled the above class' full name becomes my.library.Book. This applies to all classes in the file, or any other file which uses the same package declaration.

The convention in choosing package names are as follows:

Packages and access levels

With the package concept in place, one can differentiate between several levels of cross-encounter between entities in Java:

The three modifiers public, protected, and private determine what types of encounters are allowed for a thing as below:

Access Levels
Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N

Encapsulation example:

Consider two Java source files, valididty of access is indicated in the source:

File 1

    package a;

    class A {
        private int x;
        protected int f() {...}
        public int g() {...}
    }

    class AA extends A {
        public int h() { return super.x; } //ERROR: private
        public int k() { return super.f();} //VALID
        public int l() { return super.g();} //VALID
    }

File 2

    package b;
    class B {
        A a=new A();
        public int f() {return a.x;} //ERROR: private
        public int g() {return a.f();} //ERROR: protected, and we are not in the same package
        public int h() {return a.g();} //VALID
    }

Encapsulation rules of the thumb

When using public, protected, and private keywords follow these principles:

Example: Bank account

In the bank account example we must use access modifiers as follows:

    package example.com;

    public class BankAccount {
        private String firstName, lastName;
        private double balance;
        private String password;
        private int miles;
        public BankAccount(String firstName, String lastName, String password;) {
            this.firstName=firstName;
            this.lastname=lastName;
            this.password=password;
            balance=0.0;
            miles=0;
        }
        public String getFirstName () { return firstName;} //getter method
        public String getLastName () { return lastName;} //getter method
        public boolean checkPassword(String password) { return password==this.password; }
        public void depositMoney(double amount) {balance+=amount;}
        public void drawMoney(double amount, String password) { 
            // change data field, log the transaction for legal responsibility
            ...
            }
        public boolean setPassword(String oldPassword, String newPassword) { ...}
        protected void addMiles(int amount) { ...}
        protected int getMiles() { ...}
    }

Note the following: