Quote:  "Hide data fields from clients by declaring them private 
         and make data fields accessible only through public 
         methods."  
		    - ancient software engineering proverb ;^)


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                Methods and Constructors
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

------------------------------------------------------------------
Part I - modularizing the main program with methods
------------------------------------------------------------------
We've written several procedural programs that contain only one method - the main method. However, it is considered better programming style to partition the main method by specific tasks, particularly if the code gets longer than a page or so. These smaller tasks are called methods. Each method should ideally have one task to accomplish and should be named appropriately after the task.

For example, consider the program CalculateWeight.java, shown below

----------------------------------------------------------  

// This program takes a mass in kilograms and calculates
// the normal force on the object on Earth

import javax.swing.*;  // for JOptionPane
import java.util.*;    // for Scanner
import java.text.*;    // for DecimalFormat class

class CalculateWeight {
  
  public static void main(String[] args){
    
    // standard acceleration of gravity on Earth
    final double GRAVITY_M_PER_SEC = 9.81;
  
    System.out.println("Welcome to the normal force "+
                       "calculator!\nYou will be "+
                       "asked to enter a mass\nin kilograms "+
                       "After this,\n"+
                       "the weight on Earth will be displayed");
    
    double mass = 
         (new Scanner (JOptionPane.showInputDialog
              ("Please enter the mass in kilograms: ")))
                  .nextDouble();
    
    double weight = mass * GRAVITY_M_PER_SEC;
    
    DecimalFormat df = new DecimalFormat("0.00");
    
    System.out.println("A mass of "+df.format(mass)+
                        " kg has a weight of "
                        +(df.format(weight))+" N");
  }
}

------------------------------------------------------

In this program, the main method contains a long introductory print statement. It would be better programming style to put this introduction in a separate method, possibly one whose only task is to output the print statement as follows:


    public static void printIntro() {
        System.out.println("...");
    }
Since this is a static method, being called from a static method, this method would be called using the line
    printIntro();
in the main method. Notice that, since the method printIntro returns "void" and takes no input parameters, we can call it using very simple syntax - the method name followed by a pair of empty parenthesis.

Let's look at the header of method printIntro and recall what each part signifies:

    1. visibility modifer (public, private, protected or blank):
           o  public  = usable by all client programs
           o  private = usable only from inside this class
           o  protected = usable from inside this class and from
              inside all descendants of this class
           o  blank = usable from all programs in the same package

    2. access modifier (static or blank):
             static  = "class method"
                     o  Called using ClassName.method() from
                        client programs (other classes).
                     o  Called using method() or
                        ClassName.method() from inside same
                        class.

             blank = "instance method"
                     o  Called using objectName.method() from
                        client programs (other classes).
                     o  Called using method() or this.method()
                        from non-static method in same class.
                     o  Called using objectName.method() from
                        static method in same class.

              NOTE: A static method can access an instance method
              (or instance variable) ONLY through an object, not
              directly.
 
     3. return type: any variable type.
              AT MOST ONE PRIMITIVE OR OBJECT TYPE CAN BE 
              RETURNED FROM A METHOD

     4. method name:  Use standard naming conventions, lowercase
                      first letter followed by capital letters on
                      subsequent words.

     5. input parameters:  (type1 localParameterName1,
                            type2 localParameterName2,
                            ...
                            typeN localParameterNameN);

There is only one type of method that has no access modifier or return type and this is called a CONSTRUCTOR. Technically, a constructor is not a real method. It is used only for object creation and memory allocation. We will discuss constructors in part II.

If we wanted to call a method to calculate the weight in program CalculateWeight, we could write a method with the following header:


     public static double calculateWeight(double mass) {
         double value = <calculation of weight>
         return value;
     }
Notice that, when a return type other than void is specified in the method header, there must be at least one return statement and it should be the last statement executed in the method (or be the last statement on every possible branch of execution through the method).

If we add the calculateWeight method directly to the CalculateWeight program, we have a problem because the conversion factors are only visible inside the main method (because that's where we declared them as constants.) However, we can make these constants GLOBAL by declaring them outside the body of any method. If global data members (constants or instance variables) are only going to be used by static methods, the global members should also be declared static.

The modified CalculateWeight program, with separate methods to print the introduction and to calculate the weight, is shown below:

----------------------------------------------------------  

// This program takes a mass in kilograms and calculates
// the normal force on the object on Earth

import javax.swing.*;  // for JOptionPane class
import java.util.*;    // for Scanner class
import java.text.*;    // for DecimalFormat class

class CalculateWeight2 {
  
  // standard gravity on Earth (GLOBAL CONSTANT)
  final static double GRAVITY_M_PER_SEC = 9.81;

  public static void main(String[] args) {
  
    // **call a method to print instructions
    printInfo();           
    
    double mass = (
        new Scanner 
           (JOptionPane.showInputDialog(
             "Please enter the mass in kilograms: "))).nextDouble();
    
    // **call a method to calculate the weight
    double weight = calculateWeight(mass);
    
    DecimalFormat df = new DecimalFormat("0.00");
    
    System.out.println("A mass of "+df.format(mass)+
                        " kg has a weight of "
                        +(df.format(weight))+" N");
  }

  // Displays introductory information about the program
  // for the user
  public static void printInfo() {
    System.out.println("Welcome to the normal force "+
                       "calculator!\nYou will be "+
                       "asked to enter a mass\nin kilograms "+
                       "After this,\n"+
                       "the weight on Earth will be displayed");
  }

  // Given a mass as input, this method returns the weight of 
  // the mass in Newtons
  public static double calculateWeight(double mass) {
    return (mass * GRAVITY_M_PER_SEC);
  }
}
---------------------------------------------------
Note that the "static", "public", and "private" access modifiers are only used with data fields when they are declared OUTSIDE method bodies. Data fields declared outside method bodies are "global", accessible throughout the class. The modifiers have no meaning inside method bodies. Every data field declared inside a method body is local to that method, so it can't be accessed directly from outside the method.

Note that method bodies do not overlap (i.e., are never nested).

------------------------------------------------------------------
Part II - Defining objects with instantiable classes
------------------------------------------------------------------
Every class has the potential to be an object. However, classes with only static methods and static data fields will produce objects with no unique data attributes and no instance methods, in which case the objects created will be, for all intents and purposes, empty and useless.

An INSTANTIABLE class typically has one or more non-static data fields declared outside method bodies and one or more non-static methods. Such a class may, or may not, have a main method. Let's look at an example. Suppose we wanted to create a class to represent Students. We could write the following simple class:

--------------------------------------------
class Student {

  private String id;
  private double gradePointAve;

  // zero-parameter constructor
  public Student() 
  {
    id = "0000000";
    gradePointAve = 0.0;
  } 

  // 2-parameter constructor
  public Student(String sid, double gpa) 
  {   id = sid;
     gradePointAve = gpa;
  }

  <other methods>  

  public static void main (String[] args) 
  {  
     // ***call to 0-parameter constructor
     Student student1 = new Student();
     // ***call to 2-parameter constructor
     Student student2 = new Student("378452177", 3.87);
     <more code>
  }

  <other methods>

}
-----------------------------------------------  

From this class definition, we can see that a Student object contains the data fields (data members) id and gradePointAve and that these members are instance variables because they are not prefaced with the "static" modifier.

Notice the line "public Student() {". This looks like a method call because of the parentheses after Student. But there is no return type and the method name does not follow standard naming conventions for methods (first letter is uppercase). What's up with that?

"public Student() {" is the header of a CONSTRUCTOR. A constructor always has a name matching the name of the class that contains it.

The constructor is called when the statement

       Student student1 = new Student();
is made from some other method in the Student class or in a different class. The top constructor in the Student class takes no input parameters, and is therefore known as a "zero-parameter" or "no-parameter" constructor. The purpose of a no-parameter constructor is typical of constructors in general: it initializes the instance variables in the student object. It is important to initialize the instance variables to ensure that the object is created with a valid state (i.e., a state that will not lead to errors.)

The line "public Student(String sid, double gpa) {" is also a constructor. However, this is a "2-parameter" constructor, since it has two input parameters. Notice that the parens after the method name contain the usual (<type> <localName>, ...) syntax as method headers. This constructor also initializes the data fields of a student object, but the values of these data fields are specified when the constructor is called with a statement such as

       Student student2 = new Student("378452177", 3.87);
Having two (or more) methods with the same name is called METHOD OVERLOADING and constructors are frequently overloaded. Why?
      -  There may be objects created before the
         values for the data fields are known.  The
         constructor is used to set instance variables 
         to some default values so that the newly created 
         object will be in a valid state.  

      -  There may be objects you create after you know the 
         values to be assigned to the instance variables, in
         which case the non-zero parameter constructors are
         useful. 

Any method can be overloaded. To avoid confusion, methods with the same name must have different headers. The difference in the headers must be in the type and/or number of input parameters.

Notice something different about the data field declarations in this class? They are global to the class, they are non-static, and they are declared PRIVATE. As a general rule, all data fields are declared private and are therefore accessible only within the class body.

Private data fields can only be accessed within the body of the class in which they are declared. The convention of declaring data fields private upholds one of the major principles of object-oriented languages: Information Hiding, or Data Encapsulation. If the state of an object can be altered only by its public methods, then the manner in which the state is modified can be controlled by the programmer.