Abstraction, Encapsulation & the Class  Peter Komisar

References:
'Just Java'   Peter van der Linden,
'Java 1.1 Certification Study Guide' Heller-Roberts
'Java 1.1 The Complete Reference' Naughton-Schildt                                                               latest revision Sept 26 / 2000


Object-oriented programming evolved over the past thirty years in tandem with the
development of Graphical User Interfaces. The first object oriented language was
Simula-67, presumably released in 1967. Smalltalk was the first really successful
object-oriented language. Java may be thought of as an amalgam of the object-
oriented principles of Smalltalk, the architectural structure of UCSD Pascal and
the syntax of C and C++. For more detail see Evolution to Java.


Object-Oriented Programming derive from four key ideas;

 1) abstraction  2) encapsulation  3) inheritance  and  4) polymorphism

In this note, we look at briefly at abstraction and then at encapsulation. At the same time
we describe the object-oriented building blocks of the java language.

Abstraction

One definition Webster' Dictionary provides for the word abstract is "Considered apart
from the concrete" and for abstraction, "Separation or removal". Abstraction in computer
programming, and more specifically, in object-oriented programming is the process of
extracting key characteristics of a real-world system to achieve some programming objective.
These characteristics are described in a form which allows them to be modeled, implemented
and run on a computer system. Abstraction is the process of eliminating details which are
irrelevent to the the task a program is designed to do.

example. nephew //  the person is a complex, real world system

To an aunt
Tom, asides from being a nephew,  might be represented in a record somewhere that might
have the following information.
 
 nephew  Tom
 birthday  May1,1967
 favorite_color   blue
 likes  car_mags, ping_pong

// You could analyse this record as describing a  class of entity called nephew. Tom can be
// thought of as an object of type nephew

The aunt's objective may be not to miss sending a card any family member's birthday. She
may not be interested in how Tom is doing at school. The aunt abstracts the information
from the complex system that she is interested in.

To a sports coach

The sport's coach abstracts a different collection of characteristics and / or  behaviour to
describe Tom.
 
 name  Tom Thompson 
 weight   220lbs
 atheletics  fast_sprinter
 grade_point_average  C+

The coach may be interested in how Tom can serve on the school team and is watchful that
his marks permit his participation. The coach is not likely to be interested in Tom's favorite
color. Again, an abstract representation has been made to suit some informational objective.

Abstraction at the design level may be concerned with what a set of objects have in common.
For instance you might be trying to design a program that creates views of different dog types.
We could start by trying to determine the fundamental characteristics dogs have in common.
These might characteristics such as tail length and loudness of bark or behaviour like how the
dog walks or hunts
An abstract Dog class can be created that itemizes these key characteristics and behaviour
without providing details of implemetation. Then classes like GermanShepard or Collie can be
derived from this abstract parent class providing the specific details that describe each variation.
In this excercise we abstract the information we are interested in. In this abstraction heart rate
is probably meaningless information.
A personal phone book is a good example of an abstraction of the public phone directory.
A specialized glossary is a good example of an abstraction of Webster's dictionary.

Encapsulation

In Computer Science, combining important characteristics,  together with operations which
are performed on these variables  forms what would be called an abstact data type. In early
computer languages this notion of coupling data with operations was a loosely defined or non-
existent notion. In the days of submitting code to mainframes via punchcards, a program might
have the code part first and any data that was needed would just tacked the end after a symbol
like $DATA (PL\1). Even here the notion that code and related data are associated is evident.

In object-oriented programming, data and operations are formally coupled in the data structure
called the class. The class acts as a container for it's members. A class members include fields,
(also called variables) which hold characteristics or properties. In our dog example that might
be a number representing the loudness of the bark. The class member that describes behaviour
is the method. (a.k.a. functions, procedures, routines or operations.)  Methods are the verbs
or action parts of a class. In the dog class that might be a method called walking. Java classes
also hold constructors. These are special methods whose sole job is to create what are called
new instances or objects of a given class. (If we think of Tom in our earlier example being an
object of type nephew, Tom's constructor would basically do the job of setting up Tom's info
in the memory of the computer.)
Sometimes other inner classes are also included as members of a class but this is uncommon.
What's not mentioned as being members of a class are members a class might inherit the use
of from a parent class. These are technically members of the parent or the parent's parent.The
ultimate parent class is Object class. Object class is the root class from which all classes in
Java derive.

As alluded to in our dog example, object-oriented languages allow the creation of user defined
types. We created the class type Dog and were on the way to creating GermanShepard and
other concrete types. Built into the java language is control over the degree to which data and
operations can be accessed  from outside the class. This is the work of  the access modifiers,
private, no-modifier, protected, and public.
 
 
 Comparing the Java class to the equivalent C code
 // This is a reduced version of Van der Linden's more detailed transition in 'Just Java' 


In C the structure where the data is not coupled to the code that works on the data.

 typedef struct{
          int speed;
          int handling;
          int braking;
          }Car                                                           /* C code */

   int  get_performance_rating(Car *this){
          return (this->speed) + (this->handling) + (this->braking);
          }

 /* In this C example where a data type holds related data. Seperately, a C function is defined 
      which acts on this data, in this case it returns a numeric performance rating based on speed, 
      handling and braking                                                                                                                       */

 C's action parts are called functions. Java calls it's action parts methods.



 //  Here's the Java code equivalent

 class Car{

/* here are three primitive variables of type int */

          int speed; 
          int handling; 
          int braking;

 /* here's a java method that takes no arguments and returns an int */

          int getPerformanceRating( ){ 
          return (speed + handling +braking);
          }
      }

 Here's how Java does the same thing. The action code, a java method, is encapsulated along 
 with the data fields, (speed, handling and braking) in a structure called a class. This is a tight 
 binding as these data members cannot be separated, having been defined inextricably as being 
 part of the same class. Adding keywords which modify a user's access to the classes data and 
 methods, for instance the access modifier private could have been used to limit access of the 
 three int variables, further increases the tightness of the encapsulation.

Class, Object & Primitive type



 
 
Type   Description
class  The template or type describing grouped fields and methods. (The class is a
 logical derivation of older data types such as typedefs, records and structs.)
object  Also called 'an instance' is a construction which creates an image or copy of the 
 class template. It has the same fields and methods as the class it is printed from 
 which can be used with different values
primitive  Also called prime types as they are not composed of any other types, they 
 are boolean,  byte,  short,  char,  int,  long,  float, & double       // 8 in all

Class

A class provides a template for creating objects. Exact copies of the class are called objects
(or new instances). Objects can be used as containers for unique sets of variable data. An
object of a class type is declared, when you create a reference. You may think of a reference
as a nameable container for a 32-bit address. A reference provides a handle for accessing a class
or an array stored somewhere in memory. (A reference is technically a kind of  'limited' pointer
You may of heard of pointer arithmetic but will not need to know about it as Java doesn't
permit pointer manipulation. Also, Java automatically takes care of dereferencing pointers.)

// dereferencing is going to a reference variable, getting the memory address stored in it, then going to
//  this address to get the values stored there. In Java getting the address is taken care automatically

Declaration

Following is a declaration of three object variables of the class type Car. An address is retained
for each of object variable, chev,buick and ford. No memory space beyond that in which the
address is stored has been allocated, nor has any objects been created.

Car  chev, buick, ford;

When a reference type is declared in a class, it is assigned the null value by default. null
is what a reference points to when it is not pointing to an address in memory. null has the
value 0 in underlying system. (A reference created within a method or constructor has to
be set to null overtly, as there is no default initialization inside methods and constructors
as in  String s = null; )

Now the object variable of type Car can be assigned a new instance of the class type Car.

chev = new Car( );

Instantiation

There are situations where a new class object may be instantiated without being assigned a
reference as exampled below. Instantiation boils down to placing the new keyword in front
of the special method called the constructor which is used to create new instances of a class.

new Label("not referenced");

// here's a bit of code to show where you might use an unreferenced class instance

someContainer.add( new Label( "used_unreferenced" ));
 
 
The temporal life of objects


 Objects are referred to as instances as they have a  temporal life that starts with invoking their 
 constructors via the new keyword. (We look at constructors below). Technically they last until 
 they are dereferenced or until the program ends. Java has a mechanism to store objects called 
 Serialization so now objects once created may live forever, well at least as long as your mass 
 storage device. Classes are typically stored  persistently in  mass-storage  memory. Classes once 
 created act like they are immortal, as if they had no beginning. The runtime environment  takes 
 care of loading and building classes before copies or new instances are made of them.
.

Assignment

Most often, the new instance created in the process of instantiation, is assigned a reference which
gives the user a handle to access the objects fields and methods. Declaration, instantiation and
assignment can be put together in a single operation as follows.

Car buick = new Car( );

// buick is now referencing an object in memory of type Car.


The Dot Operator

// Method Invocation

Classes can contain a combination of all or none, of variables, constructors and methods (and
even other classes in the form of inner classes.) Each of these elements contained in the class
are called the class' members. Once an object has been instantiated using the new keyword,
a member method can be 'called' or invoked. The member method is called by suffixing the
method name to the reference identifier, separating the two with the dot operator (a period ).
In the following example, the getPerformanceRating( ) method is called on the new instance
referenced by the identifier buick. This method returns an int value. A primitive variable of type
int named rating is set up to to receive the assignment.

int rating = buick.getPerformanceRating( );

Sometimes you hear of a method being called on the object. This is 'programmer's talk'
for the process of calling or activating a method which is a member of an object

// Variable Invocation

Similar to a method call, a field or variable of the object can be accessed via the dot
operator. Here's an example from the Car class.

int theSpeed = buick.speed;
 
 
 more on the Dot Operator


 Besides accessing a class or objects members, the dot operator is also used in referencing 
 packages and classes within packages. For example, you  might  place  import  java.awt.event.*;
 at the top of a class you are creating to make all the action  interfaces and event classes housed 
 in the event package available for your  use in a class you  are creating.
.


Constructors

A constructor is a unique and privileged method which is used to create and initialize new
objects. When creating the Car instance above, we were invoking the class constructor.
Creating a class instance using the constructor with the new operator is called instantiation.
As shown above, combining declaration and instantiation looks like

TheClass  ref = new TheClass( );

1) Constructors share the class name 2) and have no explicit return type, the class object
created being the implicit return type. Constructors are not inherited so must be explicitly defined
in each class. The exception is the 'no-arg' default constructor provided automatically when no
other constructor is defined.
 
 
More on Constructors

 In a later section we discuss inheritance where a subclass is formed by extending or inheriting the 
class members of the parent class. In this situation, a child class can dictate which form of the parent
constructor it wishes to inherit from. The keyword super in the form super( ) is used, matching the
argument list of the target constructor in the parent. In the following example Car is defined with two
constructors.

          class Car{
                 //variable declarations
                              /* Constructors */ 
                      Car(String options){ 
                          // build car with standard options
                          }
                     Car(String options, String customization){
                         // build car with non stock options
                        }
                //methods 

  Here class SportsCar is declared as a subclass of Car. It is invoking the parent constructor
  which takes standard options so that is the form of the parent class from which the child class
  will inherit.

       class SportsCar extends Car{
            //variable declarations
                          /* Constructors */ 
                 SportsCar(String options ){
                     super(options)       // passes control to the parent constructor with matching signature
                      }
                 }



Rule: The call to super or this must be the first statement in the constructor


 A similar situation exists if you want to use the another constructor in the same class. The this  keyword is used, matching the signature of the constructor you wish to invoke. The constructor signature is it's name and argument list. Following is an example of a constructor building on the
work of an adjacent constructor.

   public class Limo{
           //declarations
          Limo(String stretch, int specSheet1, int specSheet2, int specSheet3){
           //complex processing
          }
     Limo(String bulletProof){
           this(BulletProof, 1,2,3);  // calls the adjacent constructor matching this argument list
         // then do more construction
          }
     }



Events in Constructor Invocation

1) memory for the object is allocated
2) before object allocation, memory is cleared and fields assume default settings
3) the constructors are allowed to run, referencing other constructors if called via this or super
4) if super is not called explicitly, the compiler inserts a call to super which calls back recursively 
    up through the class hierarchy until Object class is reached
5) Data fields with explicit initializers are executed. (for constructor-less anonymous classes)
6) The remaining constructor statements are executed.
.

// reminder: java has no destructors as memory recollection is automatic.

Methods

Methods are defined within classes and have the form described below. They are symbolized
by the presence of an identifier followed by a pair of round brackets. In Java, methods must
always have a return type. If they have nothing to return they are declared as returning void.
Whereas variables declared in the scope, (the area between two curly braces) of a class have
default values assigned, variables defined to the local scope of methods (and constructors)
must have their values explicitly assigned.  // class variables vs. method or local variables

The Form of a Method
 
 opt_Modifier returnType methodName (opt_ParameterList) opt_ThrowsClause { // statements }
 opt_Modifier  -a method may have modifiers such as public or static associated with them.
 returnType  -a method must have a return type. If the method returns nothing it declares 
   it  returns void 
 opt_ArgumentList  -a method may take zero or more parameter declarations within it's round braces
 opt_ThrowsClause  -if a method can throw an exception it must be declared showing it throws
 the exception
 //statements   - the action statements of a method are defined within the scope of curly braces 

Parameters are variable types that serve to receive values of arguments passed into the method. Parameters
describe the variable specification in the method's definition while arguments are the values provided to the
method. Though each has it's own meaning, the distinction between arguments and parameters seems to be
permanently blurred. Texts show methods taking parameter or argument lists.

Method Examples

Methods are the action part of the language so it is recommended by the linguists to give your
methods verbs for identifiers while variables should be identified with nouns.

The following is a pretty minimal method. It has no modifiers, returns nothing, (void), takes no
arguments, and throws no exceptions.

void doLittle( ) { // don't return anything }

Next will show a method which is private, returns a double and has two int type parameters.

private double inAndOut(int j, int k){
    {   // do something with  j & k then
           //   return aDouble
    }
Following is an abstract method. It has no body.

 abstract void showAbstract(String s);

Here' a stub method. It has an empty implementation. Nothing is done within the curly braces

void stubIt( ){  }

You are already familiar with one large method, a publicly available, class method which takes
a string array as an argument and throws no exceptions.

public static void main(String[] args) {
// defines the starting point of a programs execution
}


class MT{
int i=33;
public static void main(String[] args){
  MT mt=new MT( );      // create a new object of the class in order to call it's method
   //first print out i
  System.out.println(mt.i);
   //now run it through the method
  mt.change(88);
   //now lets check the value
  System.out.println(mt.i);
  }
void change(int i){
// i=i; doesn't change the class version of i as it is the local version
this.i=77;          //this references the class version of the variable
  }
}

Passing primitive types into methods

Primitive variables are passed into methods by value, that is, a copy of the value is passed in.
Objects use variables called  references. Reference contain an address that points to where
the object is stored. When references are passed as arguments to methods they too are passed
as copies. However a copy of an address is going the have the same effect as passing in the
actual address. So though changes made to a primitive passed into a method by copy doen't
change the original value, changes made via a method to an object's members will effect the
original.

Examples of passing primitive Variables

example

       void up (int n){                   // first we create a little method that increments an integer by one
                    n++;
                    }
                    int x = 2;                                        // here we assign the value 2 to an int variable x
                    up(x);          // we call the method passing in x which actually just passes in a copy of x
                    System.out.println("x is still " + x);  // x is the same as the copy was incremented not x

Two solutions shown in the following table are 1) to read out the change from within the scope of the
method or 2) design the method to return the changed value and use it to assign an new value to x.
 
 
.
   class PassInTest{
       int x = 2; 
      PassInTest(){

      System.out.println("x before the method call is  " + x ); 
      up(x); 
      System.out.println ("After the method x is still " + x + ". Only the copy changed.); 

      // this time the method returns a value to change x

      x=returnUp(x);
      System.out.println("Now x is " + x);

      thisInUp(x);
      System.out.println("After using the this version, x is " + x);

      }
    public static void main(String[]  args){
       PassInTest pt=new PassInTest( );
       }

  /* three methods */

     void up (int n){ 
       n++;
      System.out.println("Inside the method n is  " + n); 
       } 

     int returnUp(int n){
     n++;
     return n;
     } 
 

 void thisInUp (int n){ 
       n++;
      this.x = n;
       } 
 }
.

Examples of passing Object References
 
 
import java.awt.*;

class PassInT{
  PassInT(){
//********************************
//primitive works as expected
//********************************
  int x = 2; 
   up(x); 
  System.out.println("x is still " + x ); 

//******************************
// String is not doing what we might expect. This gets back to Strings being 
// immutable and how the objects are replaced behind the scenes in the address
// space. The copy of the reference passed in will no longer be pointing to the
// same address after the action on the string has been executed. So in the case
// of the String class, the behaviour is like that of the primitive.

// http://forum.java.sun.com/forum?14@@.eef5ef5
// http://forum.java.sun.com/forum?14@@.787bfd31

//******************************

  String q=new String("Name");
  System.out.println(q);
  add(q);
  System.out.println(q);

//********************************
// TextField is and object reference and is doing 
// doing what we expect
//********************************

  TextField tf=new TextField("X");
  System.out.println(tf.getText());
  add2(tf);
  System.out.println(tf.getText());

//********************************
// StringBuffer represents a mutable String
// and is also doing what we expect
//********************************
  StringBuffer qb= new StringBuffer("Plane");
  System.out.println(qb);
  add3(qb);
  System.out.println(qb);
}
//*******************************
//main
//*******************************

public static void main(String[]args){ 
  new PassInT();
  }
//********************************
//  methods
//********************************
void up (int n){
    n++;
    }

void add (String s){
  s.concat(" is a String");
  }

void add2(TextField t){
  t.setText("Y");
  }

void add3(StringBuffer sb){
  sb.append(" is a StringBuffer");
 }

static

The static keyword creates a member which exists on a per class rather than a per object basis.
 A static member is created once when the class it is in is loaded.
 
 
 Details on the static keyword

 The static keyword can be applied to 1) variables, 2) methods, 3) blocks, and 4) classes.
 The static keyword creates a member which exists on a per class rather than a per object basis. 
 A static member is created once when the class it is in is loaded.
 A static or class variable  might be used as a counter in a multithreaded environment where several
 'source' objects are incrementing the counter to arrive at some common total. Another example where a
 static variable might be used is to describe the number of bars of gold in reserve at a treasury. Regardless
 of the number of instances of  a BranchWithdrawal class which may be created, each would have the
 same static variable describing the absolute amount of gold each account was withdrawing against.

 Static methods can only work with static data and can't reference object data The common compiler
 complaint is 'You can't make static reference to a non-static variable'. To work around this objects are
 instantiated inside static methods and from there an objects members are accessed via the object's 
 reference.

 You do this when you create instances of classes inside main,  public static void main(String[] argv)
 // sometimes you see args for arguments plural and argv for argument values

 Other examples of static methods are , valueOf ( different types ) in the String class and all the methods 
 of the Math class are static When 'calling' a static method it can be referenced via  the class name or 
 the instance of the class. It is considered better style to access static methods via the class name in 
 order to communicate method being accessed is static.

 A static block  is a block of code enclosed by curly braces and marked 'static'. The block is enclosed in a 
 class and outside any method. The block is executed when the class is first loaded in the JVM. In Java 
 classes are loaded 'dynamically', that is at the time they are referenced by another class. Following is an 
 example of a static block.

 static { // this is the  form of a static block  }

"Loading a class 
 - reading in and converting a stream of bits from a file or URL into a known class inside the JVM"
                                                                                                                                        -Peter van der Linden.

 Static Classes (aka a nested top-level class
 The declaration of an entire class as a static member of another class. Only such inner classes can be 
 marked static. Static classes by definition can't be instantiated. Static classes  have no 'this' reference 
 which is only meaningful when used as an instance reference.  As with other members marked static, 
 static classes can only access static and not instance data. 
.

final applied to variables, methods and references

The final modifier makes a data member constant. With regard to final variables and methods,
the actual values become unchangeable. When final applies to a reference, that reference cannot
change what it points to.The fields of the object being referenced though still can be changed.
Classes can also be final. The Math class is final (and it's methods are static). String class is also
final. // can apply to class, method, or a field
 

Access Modifiers

1) private makes members accessible only from within the class

2) no access modifier also called friendly, or package access or default
    members are accessible from within the same package.

3) protected members are accessible from within the package and from subclasses outside the
    package.(Children classes still have access to protected members in parents package.)

4) public members are accessible anywhere the class is excessible.

Classes can marked public or have default access. They can't be  protected or private.



Notes:
Some of the methods deprecated going from Java 1.0 to Java 1.1
set Enabled( ) replaces enable( ) and disable( ), setVisible( ) replaces show(  ) and hide( ),
setSize( ) replaces resize( ) [getSize( ) is still good], setForeground(  ) & setBackground( ) are the same
show(  ) is confusing as it is deprecated in some classes yet not in others in it's direct inheritance lines.

main( ) vs. main( ), C to Java
1) main in C returns int while Java returns void and is designed this way
2) The '0' args array argument passed to main is the first command line argument in Java unlike C where it is the name
of the program. Java already 'knows' the name as main( ) is contained in the class whose name is the file/program.