5: Object Oriented Programming

What We Will Cover


Illuminations

Questions on Assignments?

  • A4: Using Arrays (3/9/05)
  • About how many comparisons are needed to sort an array of 100 elements using the unmodified bubble sort?
  • About how many comparisons are needed to sort an array of 100 elements using the enhanced bubble sort?
  • How much did our improvements to bubble sort improve its performance?

Questions from last class?

5.1: Introduction to Object-Oriented Programming

Objectives

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

  • Describe what classes, objects, methods and instance variables are
  • Declare a class and use it to create an object
  • Call an object's method to perform a task

5.1.1: About Classes and Objects

  • Everywhere you look in the real world you see objects
    • People
    • Animals
    • Plants
    • Buildings
    • Cars
  • Humans, including programmers, think in terms of objects
  • Humans learn about objects by studying their attributes and behaviors
  • Attributes are things like: size, shape, color and weight
  • Behaviors are what an object does, like:
    • A person walks, runs, crawls, talks and sits
    • A plant grows and wilts
    • A car accelerates, brakes and turns
  • Object-oriented programming (OOP) grew out of using software to model complex systems in the real world
    • Spread of disease in humans, animals and plants
    • Design of buildings or other large objects
    • Design of cars
    • Ecosystem simulation
    • Network routing
    • Weather prediction
  • Object-oriented design (OOD) models software like the way people study objects in the real world
  • It takes advantage of relationships where objects of a certain class, like buildings, have similar attributes and behaviors
  • OOD provides a natural and intuitive way to view software design
    • Once you get used to it
  • OOD models objects by describing their attributes and behaviors
  • It also models communication between objects
  • Just as people send messages to each other, software objects send messages
  • For example, a house object may receive a message to open or close a door

5.1.2: Modeling Objects in Software

  • Let's use a simple analogy to help us understand classes and objects
  • Suppose you want to build your own home
  • You find the blueprints of a house that you like
  • These blueprints describe all the attributes of the house, like:
    • size
    • shape
    • location of rooms
  • Within this blueprint are the actions you can perform on your house, like:
    • Open doors in the front of the house
    • Turn on a furnace to heat the house
  • We can use this analogy to introduce some of the OOP concepts
  • The blueprint is like a class in OOP
  • We create a description of the object by writing a class
  • A class describes the attributes of an object using instance variables
  • With class House, we might have variables such as:
    • double length: the length of the house
    • double width: the width of the house
    • boolean frontDoorOpen: whether or not the front door is open
  • Instance variables are said to hold the state of an object
  • A class also describes the behavior of an object using instance methods
  • For example, class House might have a method like:
    • void openFrontDoor(): set data values to show the door as open
  • However, a blueprint of a house is not a house
  • Before you can live in the house a construction crew must build it
  • The construction crew uses the blueprints to make the house
  • Similarly, you must create an object of a class before you can use an object
  • After an object is built, you send messages to an object
  • How we send messages to a real house is we open the door
  • To send messages to a software house, we call its methods

5.1.3: Declaring a Class with a Method

  • Let us continue our analogy by writing a class for a house
  • We will keep it simple since we only want a simple model
  • All classes start with a statement declaring the class
  • For our first house class, we include a method to open the front door

Class House

1
2
3
4
5
public class House {
    public void openFrontDoor() {
        System.out.println("Opening the front door");
    }
}
  • The class declaration begins at line 1
  • The keyword public is an access modifier
    • For now we will just declare every class public
  • Every class declaration includes the keyword class followed by its name
  • In addition, ever class's body is enclosed in a pair of curly braces
  • Note that our class does not have a main() method, unlike other classes be have built so far
  • We still need a main() method for every application
  • However, we will put the main() method in a different class

Instance Method

  • The method declaration begins at line 2 with the keyword public
    • This indicates that the method is "available to the public"
    • This means that the method can be called from the outside of the class
  • After the keyword public is the method return type, name and a pair or parenthesis
  • In addition, ever method's body is enclosed in a pair of curly braces
  • The body of the method contains the statements that perform the method's tasks
  • Note that the keyword static is missing from the method declaration
  • The absence of the keyword static means that this is an instance method
  • We will cover static later in the course

5.1.4: Instantiating an Object and Calling a Method

  • Now we would like to use our House in an application
  • Every Java application must have a main() method
  • Since our class House does not have a main() method, it is not an application
  • If we were to try to execute the House class, we would get an error message
  • Exception in thread "main" java.lang.NoClassDefFoundError: House

  • To create our application, we need to either:
    1. Add a main() method to House, or
    2. Add another class with a main() method to our application
  • To get used to large applications with many classes, we will write a second class with a main() method

Class HouseTest

1
2
3
4
5
6
public class HouseTest {
    public static void main(String[] args) {
        House myHouse = new House();
        myHouse.openFrontDoor();
    }
}
  • Class HouseTest contains the main() method that begins our application's execution
  • Any class that contains a main() method can be used to control an application
  • The HouseTest class contains only a main() method
    • Which is typical of many classes that begin an application's execution

Instantiating an Object

  • To use a Java class, you usually start by creating an object of the class
    • Also known as creating an instance of the class
  • There are two steps to creating an object:
    1. Code a variable to store the object
    2. Create the object using the new operator and assign it to the variable
  • To code the variable, you write the class name followed by an identifier
  • House myHouse = new House();

Calling an Instance Method (Sending a Message)

  • In our application, we want to call the openFrontDoor() method
  • To call a method, you use the object name, a dot (period), the method name and a set of parenthesis
  • myHouse.openFrontDoor();
  • When we call the method, we are sending a message to myHouse to "open the front door"

5.1.5: Declaring Instance Variables

  • Classes usually have one or more methods that manipulate the attributes that belong to an object of the class
  • Instance variables store the attributes of an object
    • Instance variables are also known as fields
  • Each object maintains its own copy of these variables
  • To continue our analogy, we will update our House and HouseTest classes

Class House2

1
2
3
4
5
6
7
8
9
10
11
public class House2 {
    private String color;

    public void setColor(String newColor) {
        color = newColor;
    }

    public String getColor() {
        return color;
    }
}
  • The instance variable is declared on line 2 and is named color
  • private String color;
  • Instance variables are declared inside a class declaration but outside the bodies of the class's methods
  • The keyword private means that the instance variable is not accessible outside the class
  • Most instance variables are declared private
    • Declaring an instance variable as private is known as data hiding
    • We will discuss why this is done later
  • To make use of an instance variable, we use an instance method that manipulates the variable
  • In our House2 class, we have two such instance methods
    • Method setColor() will set or change the color of a House2 object
    • Method getColor() will return the color of a House2 object

Class HouseTest2

1
2
3
4
5
6
7
8
public class HouseTest2 {
    public static void main(String[] args) {
        House2 myHouse = new House2();
        myHouse.setColor("Blue");
        System.out.print("The color of myHouse is ");
        System.out.println(myHouse.getColor());
    }
}
  • Class HouseTest2 instantiates a House2 object on line 3
  • On line 4, the myHouse.setColor() method is called to set the color to "Blue"
  • On line 6, the myHouse.getColor() method is called to get the current color of myHouse

5.1.6: Summary

  • In object-oriented programming, objects are modeled after real-world objects
  • Object-oriented design (OOD) takes advantage of relationships where objects of a certain class, like houses, have similar attributes and behaviors
  • In object-oriented programming (OOP), we create a "blueprint" of an object by writing a class
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    public class House2 {
        private String color;
    
        public void setColor(String newColor) {
            color = newColor;
        }
    
        public String getColor() {
            return color;
        }
    }
    
  • Just like a blueprint is not a house, a class is not an object
  • Before we can use an object, we must create (instantiate) an object from the class
  • There are two steps to creating an object:
    1. Code a variable to store the object
    2. Create the object using the new operator and assign it to the variable
  • For example:
  • House2 myHouse = new House2();
  • One you create an object, you can "pass it a message" by calling its methods
  • myHouse.setColor("Blue");
  • Classes usually have methods that manipulate the attributes that belong to an object of the class
  • Instance variables (fields) store the attributes of an object
  • Each object maintains its own copy of these variables
  • Instance variables are declared inside a class declaration but outside the bodies of the class's methods
  • Most instance variables are declared with the access modifier private
  • private String color;
  • Since the private modifier prevents access outside an object of the class, you must use the instance methods of the class to access an instance variable
  • We will discuss why this is done in the next section

Exercise 5.1

Take one minute to prepare an answer for the following problem.

List the line numbers for the statements of HouseTest2 and House2 (shown below) in the order of their execution.

1
2
3
4
5
6
7
8
9
10
11
public class House2 {
    private String color;

    public void setColor(String newColor) {
        color = newColor;
    }

    public String getColor() {
        return color;
    }
}
1
2
3
4
5
6
7
8
public class HouseTest2 {
    public static void main(String[] args) {
        House2 myHouse = new House2();
        myHouse.setColor("Blue");
        System.out.print("The color of myHouse is ");
        System.out.println(myHouse.getColor());
    }
}

5.2: Coding Classes to Define Objects

Objectives

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

  • Describe encapsulation and data hiding
  • Design classes that create objects
  • Code instance variables, constructors, and instance methods of classes

5.2.1: Encapsulation and Data Hiding

  • Two important concepts of object-oriented programming:
  • Encapsulation: inclusion of a number of items into a single unit

    Data hiding: restricting a program from directly accessing the data stored in a class

  • When data is hidden, access is performed through methods
  • Publicly available methods are known as an object's interface

Some Benefits of Encapsulation and Data Hiding

  • Controlling access through methods helps prevent accidental data corruption
  • For example, a method that changes an objects data checks that the new value is correct before assigning it to an instance variable
  • In addition, if you decide to change the type of a data variable, you only need to change the body of the access method, which makes the change easy.
    • Other program code calling the methods does not need to change

Object Reusability

  • Encapsulation used by OOP provides another benefit: reusability
  • Objects are not standalone programs
  • Rather, they are used by programs that need their services
  • This allows one programmer to develop an object to perform one task
    • Such as displaying a graphical image
  • Another programmer can use the object in his or her program
    • Such as a Web browser

5.2.2: Defining Classes

  • Basic Syntax
  • [accessModifier] class ClassName {
        // body of the class
    }
    
  • The access modifier is optional but you should always use it for now
  • Also notice as we proceed that classes contain three general sections:
    • Instance variables
    • Constructors
    • Instance methods
  • We will look at each of these in the sections that follow

For Example

  • The following is the code for a class named Product
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Product {
    // Instance variables
    private String name;
    private double price;

    // Constructors
    public Product() {
        name = "Unknown";
        price = 0.0;
    }

    public Product(String newName, double newPrice) {
        setName(newName);
        setPrice(newPrice);
    }

    // Instance methods
    public String getName() { return name; }
    public double getPrice() { return price; }

    public void setName(String newName) {
        if (newName == null || newName.length() == 0) {
            name = "Unknown";
        } else {
            name = newName;
        }
    }

    public void setPrice(double newPrice) {
        if (newPrice > 0.0) {
            price = newPrice;
        } else {
            price = 0.0;
        }
    }
}
  • Here is a class to test it
1
2
3
4
5
6
public class ProductTest {
    public static void main(String[] args) {
        Product prod = new Product("Milk", 3.95);
        System.out.println(prod.getName());
    }
}

Access Modifiers and Data Hiding

  • Note the keywords private and public
  • Referred to as access modifiers or visibility modifiers
    • private: can only be accessed by member methods of this class
    • public: can be accessed by member methods of any class
  • Setting private accessibility for all data is a good design practice
  • Protects data by controlling access only through the public methods
  • Allows us to change how data may be stored at some future time
    • Without affecting code outside the class

Programming Style: Class Naming Conventions

  • Use nouns to name classes -- they represent objects
  • Start class names with a capital letter
  • Capital letter differentiates classes from methods and variables

5.2.3: Instance Variables

  • We now look at each section in more detail
  • Instance variables store the attributes (data) of an object
  • Each object has its own copy of these variables
  • Syntax for declaring instance variables:
  • [accessModifier] type variableName
  • For now, use the private access modifier for all instance variables
  • The type can be any primitive type or class name
  • Instance variables work just like variables you have used previously
  • Only difference is they are declared outside of any method body

Examples

    private String title;
    private double price;
    private Product myProduct;
    

Default Values

  • The compiler will initialize all instance variables to default values as follows:
    • Integer (byte, short, int, long): 0
    • Floating-point (float, double): 0.0
    • Character (char): '\u0000'
    • Boolean: false
    • Objects: null
  • Programmer can explicitly declare an initial value for instance variables
  • For example:
  • private String code = "NONE";
    private String title = "";
    

5.2.4: Instance Methods

  • Instance methods define the operations that can occur on an object
  • Performing these operations is sometimes referred to as passing messages
  • Objects use methods to pass messages to each other
  • The syntax for declaring instance methods:
  • [accessModifier] returnType methodName(parameter list) {
        // statements of the method
    }
    
  • Most of the time, you should declare methods public
  • However, if you want to prevent other classes from using a method, declare it private
  • The name of the method combined with the parameter list form its signature
  • You can have many methods with the same name in a class
    • However, each must have a different signature

Method Naming Conventions

  • As mentioned before, use verbs for method names
    • Appropriate since they perform an action
  • Also start method names with a lower case letter
  • Not required, but is a convention that professional programmers follow

Set Methods

  • When variables are declared private, you may still need to modify them
  • Use public methods to allow modification of the data
  • Called set methods (a.k.a. mutator methods)
  • Use the name of the variable with the word set prepended
  • Such methods should verify the value is correct before setting it
  • For example:
  • public void setPrice(double newPrice) {
        if (newPrice > 0.0) {
            price = newPrice;
        } else {
            price = 0.0;
        }
    }
    

Get Methods

  • Also, you often need access to private variables
  • Use public methods to access the data
  • Called get methods (a.k.a. accessor methods)
  • Use the name of the variable with the word get prepended
  • For example:
  • public String getName() {
        return name;
    }
    

5.2.5: Defining Constructors

  • Constructors are called whenever an object is created from a class
  • Its primary purpose is to initialize the instance variables
  • Syntax for declaring constructors:
  • [accessModifier] ClassName(parameter list) {
        // statements to initialize instance variables
        // other initializing statements as needed
    }
    
  • For now, use the public access modifier for all class constructors
    • Other objects call the constructor when creating new objects
  • Constructors must use the same name and capitalization as the class name
  • Constructors can have zero or more parameters, just like methods
  • Name of the constructor combined with the parameter list form its signature
  • Can have many constructors in a class, but each must have a different signature
    • Known as overloading

Example: Constructor with no Parameters

  • If you do not want to accept arguments for instance variables, code a constructor with no parameters:
  • public Product() {
        name = "Unknown";
        price = 0.0;
    }
    
  • Note that constructors with no parameters are called no-arg constructors

Example: Constructor with two Parameters

  • If you want to accept arguments for all instance variables, code a constructor with parameters for each variable:
  • public Product(String newName, double newPrice) {
        setName(newName);
        setPrice(newPrice);
    }
    

Example: Constructor with one Parameter

  • If you want to accept only some arguments, code a constructor appropriately:
  • public Product(String newName) {
        setName(newName);
        price = 0.0;
    }
    

Default Constructors

  • If the programmer does not define a constructor, then the compiler supplies an empty one like the following:
  • public Product() {}
  • However, if the programmer defines any constructor, the compiler does not
  • You should always define your own no-arg constructor

5.2.6: Summary

  • OOP addresses the problem of data protection through encapsulation and data hiding
  • Encapsulation and data hiding allow you to change the inner workings of a class without affecting other classes.
  • When you define classes, you code three general sections:
    • Instance variables
    • Constructors
    • Instance methods
  • Instance variables store the data of an object
  • Constructors are called whenever an object is created from a class
  • Instance methods are the operations that can occur on the object
  • Access modifiers control access to variables, constructors and methods
    • private: can only be accessed by member methods of this class
    • public: can be accessed by member methods of any class
  • Use private for all variables and public for most methods
  • Use "set" methods to control setting of new values to private variables
  • Use "get" methods to return values of private variables

Exercise 5.2

Take one minute to prepare an answer the following question:

  1. Given a class named Timer, which of the following is a valid declaration of a constructor:
    1. void Timer() {}
    2. Timer Timer() {}
    3. private final Timer() {}
    4. Timer(Timer t) {}
    5. public static void Timer(String args[]) {}

5.3: Working with Objects and References

Objectives

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

  • Discuss the differences between primitive and reference types
  • Use classes as method parameters
  • Describe the keyword this
  • Discuss garbage collection and finalizers
  • Prevent shadowing errors

5.3.1: Primitive Types vs. Reference Types

  • Data types in Java are divided into two categories: primitive and reference types
  • Recall that primitive types store exactly one value
  • When another value is assigned, the initial value is replaced
  • All nonprimitive types are reference types
  • Thus classes, which specify objects, are reference types
  • Programs use variables of reference types to store locations of objects in the computer's memory
    • Known as indirect addressing
  • Such variables are said to refer to objects in the program
  • We saw an example of this when we discussed arrays

  • Reference types are initialized by default to the value null
    • A keyword that means a "reference to nothing"
  • As we have seen before, you must have a reference to an object to invoke the object's methods
  • Scanner input = new Scanner(System.in);
    int myInt = input.nextInt();
    
  • In this example, input is a reference to an instance of Scanner

5.3.2: Classes as Method Parameters

  • 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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class PassObject {
    public static void main(String[] args) {
        MyData d = new MyData(100);
        changeData(d);
        System.out.println("In main: " + d.getMyInt());
    }

    public static void changeData(MyData data) {
        System.out.println("In changeData: "
            + data.getMyInt());
        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 d.myInt displays in the changeData() method, we successfully passed a reference type
  • Since the data.myInt displays in the main method, we changed a data value of a reference type in a method

5.3.3: Returning an Object

  • Methods can return a reference to an object
  • We saw this before when we returned arrays from methods
  • Since arrays are objects, then we were returning objects when we returned arrays
1
2
3
4
5
6
7
8
9
10
11
12
public class ArrayMaker {
    public static void main(String arg[]) {
        char[] c = makeVowelsArray();
        for(int i = 0; i < c.length; i++)
            System.out.println(c[i]);
    }

    static char[] makeVowelsArray() {
        char[] vowelArray = {'a', 'e', 'i', 'o', 'u'};
        return vowelArray;
    }
}

5.3.4: Using this

  • 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;
    
  • A distinct area of memory is 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
  • It is 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 a constructor of Date:
  • public Date(int month, int day, int year) {
        this.month = month;
        this.day = day;
        this.year = year;
    }
    
  • We now need this to differentiate between member variables and local variables
  • Another use of this is to pass it 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
  • Useful when returning a reference after you modify the current object
  • public Data adjustDate(int days) {
        // code to adjust this Date object
        return this;
    }
    
  • Note that this is a final variable (constant)

5.3.5: Accessing Private Fields

  • One important note about private fields
  • Any object of a particular class can access the private fields of another object of that class
  • For example we could add a constructor to class House2
  • Could use another House2 object as an argument to the constructor
  • public House2(House2 otherHouse) {
        color = otherHouse.color;
    }
    
  • Note that otherHouse.color accesses the private color field of otherHouse

5.3.6: Copy Constructors

  • A copy constructor is a constructor with a single parameter of the same type as the class
  • The purpose of a copy constructor is to create an exact copy of the parameter that is a separate and independent object
  • For example, we could rewrite out previous example:
  • public House2(House2 otherHouse) {
        color = new String(otherHouse.color);
    }
    
  • Now if we change the otherHouse object, our new House2 object will not change

Notes on Strings

  • Creating a new String is actually unnecessary
  • This is because a String object is immutable
  • Whenever you create a new String, the old String is discarded
  • We will discuss this in more detail later in the course

5.3.7: Local Variables and Shadowing

  • Local variables with same name as a class variable hide the class variable
  • Any use of the variable's name will refer to the method variable
  • This is the source of many an elusive bug
  • Thus, you should not use the same name for a local variable and a class variable
  • Remember that a parameter is like a local variable but initialized in a special way
  • Thus you should use a different name for a parameter and a class variable

Example of Shadowing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Shadowing {
    public static final double LENGTH = 3.0;
    public static final double WIDTH = 5.0;
    private double length, width;

    public Shadowing(double length, double width) {
        length = length;
        width = width;
    }

    public String toString() {
        return "length: " + length + ", width: " + width;
    }

    public static void main(String[] args) {
        Shadowing sh = new Shadowing(LENGTH, WIDTH);
        System.out.println(sh.toString());
    }
}

CheckStyle to the Rescue!

  • One nice feature of CheckStyle is that it catches shadowed variables
  • Be sure to run CheckStyle and pay attention to the error messages

5.3.8: Garbage Collection and Finalizers

  • What happens to an object that is not longer used?
  • Garbage collection returns memory to system
  • An object is marked for garbage collection if there are no references to the object in the program
  • Java performs garbage collection automatically
  • You can manually choose to run the garbage collector as well
  • System.gc();
    

Finalizing Objects

  • Before garbage collection, Java gives an object a chance to clean up
  • Known as finalization and runs the finalize() method
  • You only have to worry about writing a finalize() method if you need to release resources that are not under control of the garbage collector
    • For example, a class that links to a C++ class using JNI
    • Since the C++ operates outside of Java, the garbage collector does not know how to free the resource

More Information

5.3.9: Summary

  • All nonprimitive data types are known as reference types
  • Programs use variables of reference types to store locations of objects in the computer's memory
  • You can pass an object to a method by coding a reference type as a method parameter
  • public static void changeData(MyData data)
  • When an object is created, it gets memory space for all its instance variables
  • This replication of data storage is not implemented for methods
  • Methods of the object must know which set of data to work upon
  • To keep track of which object's memory to use, a special variable is passed to all instance methods: this
  • It is possible to use the this variable inside a class
  • this.month
  • Local variables with same name as a class variable hide the class variable
    • Known as "shadowing"
  • You should not use the same name for a local variable and a class variable
  • When an object is no longer referred to by any reference variable in a program, the unused memory is automatically reclaimed ("garbage collected")

Exercise 5.3

Take one minute to prepare an answer the following questions.

Given the following code, which statements can be placed at the indicated position without causing compile errors?

public class SolarSystem {
    int planets;
    int suns;

    public void gaze() {
        int i;
        // insert statements here
    }
}
  1. i = this.planets;
  2. this = i;
  3. this = new SolarSystem();
  4. this.i = 4;
  5. this.suns = this.planets;

Wrap Up

Home | WebCT | Announcements | Schedule | Room Policies | Course Info
Help | FAQ's | HowTo's | Links

Last Updated: October 07 2005 @17:57:50