11: Object-Oriented Programming

What We Will Cover


Continuations

Homework Questions?

Questions from last class?

An instance variable is hidden (shadowed) in a method when

  1. The instance variable has the same name as the method.
  2. The instance variable has the same name as a local variable in the method.
  3. The instance variable has the same name as the class.
  4. The instance variable has the same name as the file.

11.1: Working With Multiple Objects

Objectives

At the end of the lesson the student will be able to:

  • Code classes that use other objects
  • Describe how Java passes objects to methods
  • Code arrays of objects

11.1.1: Objects as Instance Variables

  • Object-oriented programs use one or more objects to perform their tasks
  • Objects can be part of the data for other classes
  • private Product product;
  • Different applications can use the same classes to create objects

For Example

  • Following example uses the Product class
  • Note how an object of the Product class is stored as part of the ProductOrder class
  • When using another class, you do not need to know the inner workings of the other class
  • You only need to know the publicly available methods

import java.text.*;

public class ProductOrder {
    private Product prod;
    private int quantity;

    public ProductOrder(String name, double price,
            int prodQuantity) {
        prod = new Product(name, price);
        quantity = prodQuantity;
    }

    public Product getProduct() {
        return prod;
    }

    public int getQuantity() {
        return quantity;
    }

    public double getTotal() {
        return quantity * prod.getPrice();
    }

    public String toString() {
        NumberFormat currency =
                NumberFormat.getCurrencyInstance();
        String orderString =
            "Name: " + prod.getName()
            + "\nPrice: "
            + currency.format(prod.getPrice())
            + "\nQuantity: " + quantity
            + "\nTotal Amount: "
            + currency.format(getTotal()) + "\n";
        return orderString;
   }
}

  • Note that the getTotal() method does not simply return a value
  • Instead, it calculates the total by using data stored in the class
  • Uses the getPrice() method to extract data from the Product class
  • Also note method toString()
  • Returns a string with all the information for the order

11.1.2: Another Example Application

  • ProductOrderApp class is another driver application
  • Has a main method that starts an application
  • Also has a helper method
  • Helper methods are methods that perform sub-tasks for other methods
  • Usually declared private, but may be public if you like

import javax.swing.JOptionPane;

public class ProductOrderApp{
    public static void main(String[] args) {
        int choice = 0;
        String name, priceStr, qtyStr;
        while (choice == 0) {
            name = inputString("Enter a product name");
            priceStr = inputString(
                "Enter the price for a " + name);
            double price = Double.parseDouble(priceStr);
            qtyStr = inputString(
                "Enter a quantity of " + name);
            int qty = Integer.parseInt(qtyStr);
            ProductOrder po =
                    new ProductOrder(name, price, qty);
            String message = "You entered:\n"
                + po.toString()
                + "\nEnter another product order?";
            choice = JOptionPane.showConfirmDialog(
                null, message);
        } // end while
        System.exit(0);
    }

    public static String inputString(String message) {
        String input = JOptionPane.showInputDialog(
            message);
        if (input == null) {
            System.exit(0);
        }
        return input;
    }
}

  • Note that we have two applications sharing the same class Product
  • This is an example of code reuse

11.1.3: Passing Objects to Methods

  • Java passes the value stored in a variable the same way for both primitive types and reference types
  • When a method is called, the value of each argument is copied to its corresponding parameter
  • Thus an argument's value can never be changed within a method
  • Passing a reference value has implications not present when passing primitive values
  • Called method gets access to the exact same object passed by the calling method
  • Situation is shown in the following diagram:

For Example

  • Following program demonstrates passing a reference value (MyData)
  • public class PassObject {
        public static void main(String[] args) {
            int a = 100;
            MyData d = new MyData(100);
            changeData(a, d);
            System.out.println("In main: a = " + a
                + ", data = " + d.getMyInt());
        }
    
        public static void changeData(int a, MyData data) {
            System.out.println("In changeData: a = " + a
                + ", data = " + data.getMyInt());
            a = 20;
            data.setMyInt(20);
        }
    }
    
    class MyData {
        private int myInt;
    
        public MyData(int anInt) {
            myInt = anInt;
        }
    
        public int getMyInt() {
            return myInt;
        }
    
        public void setMyInt(int newInt) {
            myInt = newInt;
        }
    }
    
  • Since the original MyData.myInt displays in the changeData method, we successfully passed a reference type
  • Since the changed MyData.myInt displays in the main method, we changed a data value of a reference type in a method

11.1.4: Accessing Private Variables

  • One important note about private variables
  • Any object of a particular class can access the private variables of another object of that class
  • For example we could add a constructor to class Product
  • Could use another Product object as an argument to the constructor
  • public Product(Product p) {
        name = p.name;
        price = p.price;
    }
    
  • Note that p.name accesses the private variable of the p object
  • A constructor like this is known as a copy constructor
  • A copy constructor has a single parameter of the same type as the class
  • It creates an object that is a separate, independent object of the class
  • However, the instance variables are set to an exact copy of the object parameter
  • To use the copy constructor, you code something like:
  • Product milk = new Product("Milk", 3.95);
    Product moo = new Product(milk);
    
  • After the code executes, both objects represent the same product
  • But they have different memory addresses
  • Changing one object will not change the other object

11.1.5: Returning Objects from Methods

  • Class types can be returned from methods
  • public static Product makeProduct(String name, double price) {
        Product newProd = new Product(name, price);
        return newProd;
    }
    

11.1.6: Arrays of Objects

  • Any type can be made into an array, including class types
  • In the following, array elements are objects (i.e. type String)
  • You can call methods of the objects stored in each array element
  • For instance, length() is a method of the String class
  • public class Store {
        public static void main(String[] args) {
            Product[] store = {
                new Product("Milk", 3.95),
                new Product("Bread", 1.09),
                new Product("Cheese", 4.59)
            };
            System.out.println("We have these products:");
            for (int i = 0; i < store.length; i++) {
                Product prod = store[i];
                System.out.print(prod.getName());
                System.out.print(" @ ");
                System.out.println(store[i].getPrice());
            }
        }
    }
    

Notes on the Code

  • Code that accesses each individual array element
  • Product prod = store[i];
    
  • Code that calls a method on each array element
  • System.out.println(store[i].getPrice());
    

11.1.7: Using the this Keyword

  • Each object maintains its own set of instance variables
  • Permits each object to have its own state based on the values stored
  • For instance, consider a class Date with 3 instance variable
  • private int month;
    private int day;
    private int year;
    
  • Distinct area of memory set aside each time an object of this class is created
  • For example, if two objects are referenced by variables named a and b
  • This replication of data storage is not implemented for methods
    • Only one copy of each member method is memory
    • Every object of that type uses these same methods
  • How can this work?
  • All methods are passed an implicit parameter named this
  • For example, the method:
  • a.getMonth()
    
  • Is called as if it had the parameter this
  • getMonth(this)
  • this contains a reference to the object that called the method
    • Object a in this case
  • Parameter this is hidden, so you do not explicitly use it in method calls
  • However, you can use the this parameter inside the class
  • Used with the dot '.' operator like any other object reference
  • this.month
  • Use of this reference is optional unless needed to clarify variable scope
  • For instance, we could define an constructor of Date:
  • public Date(int month, int day, int year) {
        this.month = month;
        this.day = day;
        this.year = year;
    }
    
  • Need this to differentiate between member variables and local variables
  • Another use is to pass this as a parameter to a method
  • System.out.println(this);
  • Since this is an object reference, Java will implicitly call the toString method
  • You can also return this from a method call
  • return this;
  • Returns a reference to the current object

11.1.8: Summary

  • Object-oriented programs use one or more objects to perform their tasks
  • Objects can be part of the data for other classes
  • private Product product;
  • Different applications can use the same classes to create objects
  • When Java passes an object to a method, it copies the value of the object reference
  • Thus the method can access and change values in the passed object
  • Also, you can instantiate objects inside a method body and return a reference

Exercise 11.1

  1. Start a text file named exercise11.txt.
  2. Prepare the exercise header as described in the HowTo on submitting exercises
  3. Label this exercise: Exercise 11.1
  4. Submit all exercises for this lesson in one file unless instructed otherwise
  5. Complete the following and record the answers to any questions in exercise11.txt.

Specifications

  1. Trace the ProductOrderApp program by listing the object names and method calls in the order of their occurrence:
  2. objName.methodName()

    If an object is not instantiated, use the class name instead. For example, the first method few method calls are:

    ProductOrderApp.main()
        ProductOrderApp.inputString()
        ProductOrderApp.inputString()
        Double.parseDouble()
        ProductOrderApp.inputString()
        Double.parseDouble()
        ProductOrderApp.inputString()
        Integer.parseInt()
        po.ProductOrder()
    
  3. Record your sequential listing in your exercise11.txt file.
  4. In addition, record answers to the following questions:

Q1: In ProductOrder, what is the number of the line that instantiates the Product object?

Q2: In ProductOrderApp, what is the number of the line that calls the constructor of ProductOrder?

Q3: How many objects are created when the following line of code is executed?

ProductOrder po = new ProductOrder(name, price, qty);

11.2: Static Variables and Methods

Objectives

At the end of the lesson the student will be able to:

  • Code static variables and methods in a class
  • Call static variables and methods from other classes
  • Describe when to use static variables and methods

11.2.1: Coding Static Variables and Methods

-- Static is a crummy name (Just Java p.52)
  • Static variables and methods do not belong to objects, but to the class itself
    • Sometimes called class variables and class methods
  • Create static variables like instance variables, but with the keyword static
  • Usually add an initial value as well
  • For example:
  • private static int numObjs = 0;
    public static final double PI = 3.14159;
    
  • Create static methods like instance methods, but with the keyword static
  • For example:
  • public static int getNumObjs() {
        return numObjs;
    }
    
  • Note that static methods can only refer to static variables
  • Static methods usually receives all its data as arguments
  • Static methods are often used as general purpose methods, such as the Math methods

11.2.2: Example Using static Variables and Methods

  • Classic example: keep track of how many objects of a class are created
  • First add an object count variable to the class
  • private static int numObjs = 0;
    
  • Need to increment the variable whenever a new object is instantiated
  • Can add an increment statement to the object constructors
  • // Constructors
    public Product() {
        name = "Unknown";
        price = 0.0;
        numObjs++;
    }
    
    public Product(String newName, double newPrice) {
        setName(newName);
        setPrice(newPrice);
        numObjs++;
    }
    
  • Also need a method to retrieve the count
  • public static int getNumObjs() {
        return numObjs;
    }
    
  • Note that a static method does not have an object reference
  • Thus cannot refer to a (non-static) instance variable of the class
  • Likewise, a static method cannot call a non-static method of the class
  • With a static method, we can call the method using the class name
  • int num = Product.getNumObjs();
    System.out.println("Number of objects: " + num);
    

11.2.3: When to Use Static Variables and Methods

  • When you need multiple objects of a class, use regular variables and methods
  • If you only need a general purpose utility method, use static methods
  • For example, the Math methods
  • When you need constants shared by many classes, use final static variables
  • For example:
    • Math.PI (approximately 3.14159)
    • Math.E (base of natural logarithms, approximately 2.72)

11.2.4: Summary

  • Static variables and methods do not belong to objects, but to the class itself
  • We have been using static methods before we started studying objects
  • To create a static variable, you define a member variable with the added word: static
  • private static int numObjs = 0;
  • Static methods can only refer to static variables
  • Static variables are often used for constants
  • public static final double PI = 3.14159;
  • Static methods are often used for general purpose utility methods
    • Like in the Math class

Exercise 11.2

  1. Label this exercise: Exercise 11.2
  2. Submit all exercises for this lesson in one file unless instructed otherwise
  3. Complete the following and record the answers to any questions in exercise11.txt.

Specifications

The following code has one error that prevents its correct operation:

import javax.swing.*;

public class MyStatic {
    private int numObjs = 0;

    public static void main(String[] args) {
        numObjs = 0;
        MyStatic[] ms = new MyStatic[10];
        for (int i = 0; i < ms.length; i++) {
            ms[i] = new MyStatic();
        }
        ms[0].showNumObjs();
    }

    public MyStatic() {
        numObjs++;
    }

    public void showNumObjs() {
        System.out.println("numObjs=" + numObjs);
    }
}
  1. Correct the errors and submit your corrected code as part of this weeks exercises.
  2. Q1: What error message is displayed by the compiler, before you correct the errors?

    Q2: Whhat keyword did you use to correct the error?

11.3: Developing Classes

Objectives

At the end of the lesson the student will be able to:

  • Describe the object-oriented development process
  • Write method stubs
  • Develop drivers for testing classes

11.3.1: About Software Development

  • Roughly four main steps to developing software:
    1. Analysis: explore what is wanted and develop an initial plans
    2. Design: class design and algorithm development
    3. Implementation: coding and testing classes
    4. Deployment: final documentation and submitting the code
  • Software development is an iterative process
  • Often need to go back and repeat steps as you discover new information
  • In this section, we discuss the design and implementation steps

Further Information

11.3.2: Designing Classes

  • The organization of classes used in a program is known as its architecture
  • Classes are often organized into three main categories
    1. User interface classes
    2. Problem-domain classes
    3. Database classes
  • This is known as a three-tier architecture
  • Most of the work in this course is centers around the problem-domain classes
  • Will cover user interface classes later in this course
  • Database classes are beyond the scope of this course

Designing Problem-Domain Classes

  • Identify the classes needed for the program
    • Often spelled out in the specifications
    • If not, then read the specification looking for nouns
    • For example: customers, Addresses, products, sales
    • Nouns become the classes of the program
  • Identify the methods needed for each class
    • Often spelled out in the specifications
    • If not, read the specifications and identify the actions that need to occur
    • Usually identified by the verbs in the specification
    • These actions become the methods for the class
  • At his point, you are ready to implement the first iteration of your classes

11.3.3: First Iteration: Stubs

  • When you first implement classes, it often makes sense to use method stubs
  • You start by coding a template for the class
  • public class MyClass {
    
    }
    
  • Next you add stubs for each of the methods
  • If a method does not have to return anything, you can code an empty method
  • public void performCalculation() { }
  • If you want to see when a method is called, include a print statement
  • public void performCalculation() {
        System.out.println("Inside performCalculation");
    }
    
  • If the method needs to return a value, return a known value
  • public boolean isCorrect() {
        return true;
    }
    
  • For get and set methods, just code a simple method from the beginning
  • public int getValue() { return value; }
    public void setValue(int newValue) { value = newValue; }
    
  • You can return later and write the complete method at a later time
  • Keep stubs so simple that you are confident they perform correctly
  • If stubs get too complex, it is better to just write the method
  • Once the class is "stubbed out" you should develop a driver for testing

11.3.4: Drivers and Testing

  • Driver programs allow testing of each method
  • Once a method is tested, it can be used in the driver program to test other methods
  • Drivers allow you to complete each method of your class one at a time
  • Driver programs can be coded in a separate class
  • Another useful location for driver methods is the main method

Using main for Testing

  • The main method is often a useful location for test code
  • Each class can have a main method
  • But only one main method is required for an entire application
  • This allows you to use the main methods of most classes for test code

For Example

  • Following is an example of a main method to drive the tests for the stubs shown above
  • You add to the tests as you develop your class
  • If you make changes, you can rerun the tests to verify no new errors were introduced
public static void main(String[] args) {
    System.out.println("Calling the constructor");
    MyClass mc = new MyClass();

    System.out.println("Calling the get and set methods");
    mc.setValue(2);
    if (mc.getValue() != 2) System.out.println("Error");

    System.out.println("Calling performCalcuation");
    mc.performCalculation();
    System.out.println("Verifying the results");
    if (!mc.isCorrect()) System.out.println("Error");
}

11.3.5: Summary

  • Roughly four main steps to developing software:
    1. Analysis: explore what is wanted and develop an initial plans
    2. Design: class design and algorithm development
    3. Implementation: coding and testing classes
    4. Deployment: final documentation and submitting the code
  • Software development is an iterative process
  • Often need to go back and repeat steps as you discover new information
  • Once you identify your classes and methods, you are ready to code your first iteration
  • When you first implement classes, it often makes sense to use method stubs at first
  • You can return later and write the complete method at a later time
  • Once the class is "stubbed out" you should develop a driver for testing
  • The main method is often a useful location for test code

Exercise 11.3

  1. Label this exercise: Exercise 11.3
  2. Submit all exercises for this lesson in one file unless instructed otherwise
  3. Complete the following and record the answers to any questions in exercise11.txt.

Specifications

  1. Spend 10 minutes reviewing the specification for A10: Storing Objects.
  2. We will review the specification and design the classes during this exercise.

  3. Record a description of the design in your exercise11.txt file.
  4. After our design discussion, and as time permits, develop a first implementation of your new classes.

Wrap Up

Home | WebCT | Announcements | Schedule | Expectations | Course info
Help | FAQ's | HowTo's | Links

Last Updated: November 16 2004 @17:03:41