Intro to OOP

Things To Do First

Things To Do Later

Definitions of Classes and Objects

Read!
In addition to the material in Chapter 9.1 and 9.2, you might also find these terms helpful:

Object
Class
State, Behaviour, and Identity.

To learn more about Object Oriented Programming, check out the OOP Tutorial and OOP Basics.

Recall from the first few weeks of the course that Java is an object-oriented language. So far in working with Java, you've been writing programs. Although these programs are written in a class file with a class header (e.g. public class MyProgram { ... } ), we haven't been writing object-oriented programs. We've been writing what some programmers call hollow classes or main classes. These are classes that are just simple programs, rather than object-oriented programs

Typically, when you design an object-oriented program in Java, you work with classes that define how certain objects should appear and act in a program. A class like this defines an object as having data and behaviors. Data are defined as attributes or properties, and behaviors are defined as methods. This kind of class doesn't "run" or "execute". This kind of class acts as a template for objects used in another class. For example, a class in a file called Employee.java might contain attributes for employee name, employee number, address, and phone number, and might also contain methods for calculating an employee's weekly pay. This class is used to model Employee objects in a Java program so that a programmer can write code to create Employee objects and do things with them.

An object is referred to as an instance of a class. In other words, a class is used as the template from which an instance or an object is created. The word "instance" can sometimes mean "an example of" or "an occurence of something". In this context, an object is an instance of the class that defines it.

At home, you might have a recipe for making Hot Buttered Rum:

Hot Buttered Rum (1 serving):
2 to 4 Tbsp Hot Buttered Rum Mix
1 oz. spiced rum
almost-boiling water
cinnamon stick

In a coffee mug, add Hot Buttered Rum Mix and spiced rum.
Fill mug with water.
Garnish with cinnamon stick.

The recipe itself is like a class - it's the template that will be used every time you want to create an instance of the recipe (a mug of hot buttered rum). Each mug of the beverage you create based on the recipe is an instance of the recipe; each object you create based on a particular class is an instance of that class. You can create as many objects as you like, just as you can use the recipe to make as many mugs of hot buttered rum that you think you can handle.

The ingredients list for Hot Buttered Rum resemble the attributes or properties of the class. Attributes or properties are the data that an object of the class will contain. For example, an Employee class would define attributes for employee name and id number, and each employee object would have data values for those attributes. It's the data that often makes one object different from another object. Two employee objects might have different data values for the employee name attributes, which is one thing that could differentiate between the two objects in a program.

The Hot Buttered Rum recipe also contains a list of instructions to follow. This procedure section of the recipe can be referred to as a method. A class definition will also have one or more methods defined, which can be executed to perform tasks or to send messages to other objects. For example, the Employee class might contain a method that calculates an employee object's weekly pay, and it might contain a methods that fire and hire other employees. Objects created from the Employee class can execute these methods, and sometimes a program can execute a method right from the class itself. We'll discuss this more when we talk about static methods.

When planning a main class, we often use pseudocode. To plan a class that models objects, we can use a tool called UML, which is shown in figure 9.4 in Chapter 9.2 of your textbook.

Here is an example that summarizes the use of classes, objects, properties/attributes, and methods:

Class: Employee
Properties of the Employee class: Employee I.D., First name, Last name, Address, Phone Number, Date of Birth, Department, Salary, Job Title, etc.
Methods of the Employee class: display employee information, calculate weekly pay, fire employee, change address of employee.
Possible Employee Objects: the dean of ACES, the cafeteria lady with the freckles on her nose, your boss.

Demonstration of Objects

To learn more about how classes and objects interact, we're going to play with two classes: the Cat class and the Account class.

Extract the file OOPdemo.zip into your folder for this session.

In the folder where you extracted your files, you'll see a "docs" folder, and two class files (Cat.class and Account.class). Go into the docs folder and load index.html into your browser.

The page you're looking at is the Java documentation for the two classes. In the left-hand column, you'll see the two classes listed. You could click on one of these to see the documentation for that class. This documentation was written in the program's source code using special comment symbols. These symbols are interpreted and parsed into html by a tool called "javadoc.exe". You'll learn more about making your own javadocs in term 2.

Click on the "Cat" entry on the left-hand side to view the docs for the cat class.

Read the class description in the main window -- this tells you what the Cat class is used for (it "models a real-life cat"). If you scroll down, you can also read about the various kinds of methods available.

See if you can answer the following questions about the Cat class by reading the docs:

  1. How many methods does the Cat class have?
  2. List the method names available in the Cat class.
  3. How many methods are called "feedCat()"? How are these methods different from each other?

Once you've answered these questions, try writing the following program called "TestCat":

In class we'll be doing a demonstration of how to use the Cat class; we'll create a series of cat objects and invoke the various methods.

To try this on your own, write a program TestCat that does the following:

  1. create a new cat object and use a variable name of your choice.
  2. display your cat object
  3. feed your cat object
  4. change your cat's name, then display the cat again
  5. create a second cat object named "Morris" and coloured orange
  6. feed your cat some chicken and display him on the screen

You can check your answer with the following sample solution:

public class TestCat {
	
public static void main(String[] args) {

        Cat kitty = new Cat();
        kitty.displayCat();
        kitty.setName("Arti");
        kitty.feedCat("salmon");
        kitty.displayCat();

        Cat syd = new Cat("Sydney", "brown");
        syd.feedCat("chicken");
        syd.displayCat();
    }
}

Why are there three different "feedCat()" methods? If you read the docs, you'll notice that one method takes no arguments. When invoked, it displays "Your cat is eating..." on the screen. Another version of this method takes one string argument that represents the item you want to feed the cat. For example, kitty.feedCat("salmon"); will display "Your cat is eating salmon." on the screen. The final version of the feedCat() method takes the quantity of an item you want to feed your cat, a string for the name of that item. For example, kitty.feedCat(5, "sardines"); will display "Your cat is eating 5 sardines.." on the screen.

It is common for programs and classes to contain more than one version of a method. This is called method overloading.

Next, examine the docs for the Account class. As before, you should make sure you can answer these questions:

  1. How many methods does the Account class have?
  2. List the method names available in the Account class.
  3. What happens if a programmer uses the withdraw() method to withdraw money from the account when the account balance is 0?

The Account class is a bit more advanced than the Cat class; you'll need to put all the code that works with account objects in a try-catch block. We'll start to explore why we need to do this later on.

The Account class also contains a special method called the "toString()" method. This method is already part of Java and has a special job. When a class has a toString() method, you can display an object of that class on System.out like this:

System.out.print(myObject);

To see this work, write a TestAccount program that creates a new Account object called savings with an inital balance of 1000 dollars and an interest rate of 5%, then print it on the screen:

try
{
	Account savings = new Account(1000, 5);
	System.out.println(savings);
}
catch (Exception ex)
{
	System.out.println(ex);
}

Compile and run the program -- you should see:

Your bank account:
InterestRate: 5.0
Balance: 1000.0

When a class contains a toString() method, you can print the object's information simply by referring to the object's variable in a print statement. This causes an implicit call to the toString() method. In other words, when you stick a variable that contains an object in a print method, the print method will execute the toString() for you.

This doesn't work if the class doesn't have a toString() method. For example, try this statement:

Cat kitty = new Cat();
System.out.println(kitty);

In this case, the print statement will result in something like:

Cat@18d107f

What this shows is the name of the class that the object belongs to, and then an @ symbol, and then what we can say for now is the reference to that object in memory. This is not very user-friendly output, so when you design your own classes, you should make sure you create a toString() method for them. This is another thing we're going to learn in the next few sessions.

Note
Think about the statement System.out.println(ex); which often appears in your catch block. Based on the previous discussion, you should now realize that printing the variable ex is actually calling on the exception object's toString() method! You will get the same output if you typed System.out.println(ex.toString()); This is good to know! If you ever want to display your error in a dialog box, you would have to use ex.toString().

As an exercise, write a program to perform the following tasks:

  1. deposit 500 dollars to your savings account object
  2. display your account object again

What happens if you try to deposit 0 or fewer dollars to your account object? Try it! You should see the message:

java.lang.Exception: You must deposit more than 0 dollars!

This is because the code for the deposit method is made to throw an exception if the programmer tries to deposit an invalid dollar amount. A number of these methods throw exceptions. You can tell by reading the docs. Click on the link in the docs to the deposit() method, and you'll see a more detailed description of the method. Near the bottom of it's entry, you'll see:

Throws:
    java.lang.Exception - if the amount is 0 or less

Methods that contain this kind of information are telling you that it's possible an exception could occur if the specified conditions are met. In this case, if the amount of the deposit is less than or equal to 0. If you go back and then click on the link to "Account(double b, double r)" in the "Constructor Summary", you'll see that an exeption is also thrown if you try to make an account object with an invalid balance or interest rate.

Note
The "Constructor Summary" lists the available constructor methods available in a class. Constructor methods are special methods that are invoked when you instantiate/create a new object. We'll learn more about constructor methods in a later session.

Exercise

[solutions]

Add the following tasks to your TestAccount program:

Coding a Class

We move now from writing simple programs to writing our own classes that will eventually be used to create and use objects in other Java programs.

Try your first class:

  1. Open a new Java source file in your editor.
  2. Make sure your class header includes the word public (public class {)
  3. After the word "class", we must type the name of our class: MyMessage. A class name should indicate what this class is modeling. This class will model a message that is displayed on the screen.
  4. Save this file as MyMessage.java. Recall the rules discussed earlier regarding file names for your source files.
    • Make sure you save your file in today's folder in the prog10082 directory
  5. Classes don't execute, so they don't need a main() method. If your editor adds a main() method automatically, delete it.
  6. This class will contain an attribute called message that will contain the message to be displayed. We must define this attribute to hold a String.
  7. After the "public class MyMessage" and the opening brace, type public String message; We'll talk more about the word "public" in a later session. Your source code should now appear as:
    public class MyMessage
    {
    	public String message;
    }
  8. This class is going to contain a method that displays the message on the screen. We'll call the method "displayMessage"To create the method, type the following after the statement that defines the message attribute:
    public void displayMessage()
    {
    	System.out.println(message);
    }
  9. Compile the program and if necessary, fix any syntax errors you might have and recompile until the compile is successful.

Your complete code should now appear as:

public class MyMessage {
	
    public String message;

    public void displayMessage() {
        System.out.println(message);
    }
}

This class now models a message on the screen, but how does it work? Recall that a class is just a template. We need to instantiate (create) objects in a program so that we can make use of this class, just as you would have to create one or more bowls of sardine spread based on the single recipe. The MyMessage class is a recipe for messages that will be displayed on the screen. Let's create a program that creates MyMessage objects and uses them. Open a new Java source file and type the necessary code so that your program appears like the one below:

public class TestMyMessage {

    public static void main(String[] args) {
        MyMessage msgHello = new MyMessage();
        msgHello.message = "Hello, World!";
        msgHello.displayMessage();
    }
}

A breakdown of each of the three statements in the main() method follows:

MyMessage msgHello = new MyMessage();

This statement creates an instance of the MyMessage class and stores it in the variable called msgHello. We know already a variable is either a primitive type variable (which contains either a piece of data such as an int or a double) or an object variable (which refers to an object in memory). This variable is called msgHello and refers a new object that has been created based on the MyMessage class. Notice that we didn't say that the msgHello variable contains a MyMessage object. Instead, we say that the variable "refers" to the object in memory. Object variables are also called reference variables because they contain a reference or memory address of an object. The object itself is stored in another part of memory, and the object variable msgHello contains the address of the object.

The "MyMessage msgHello" part of the first statement defines the variable called msgHello to hold a MyMessage object. We won't be allowed to put anything other than a MyMessage object into the msgHello variable! The "= new MyMessage()" part of the statement says "make a new MyMessage object to go into the variable. If you were to read the whole statement and express it in words, you would say "create a MyMessage variable called msgHello and give it a new MyMessage object."

msgHello.message = "Hello, World!";

This statement puts a piece of text into the message attribute of the object that msgHello is referring to. MyMessage contains a definition for an attribute called "message"; each MyMessage object we instantiate has a "message" attribute. msgHello refers to an object that has a "message" attribute, and in this statement we are giving that object's "message" attribute some data. We use dot notation to access the message attribute; msgHello.message is like saying "the msgHello's message attribute" or "the message attribute of the msgHello object". The equals sign is the assignment operator, and in this case we are assigning the message attribute the text "Hello, World!". (Similarly, we used the = in the previous statement to give msgHello a new MyMessage object). If you were to express this statement in words, you would say something like "the msgHello object's message attribute gets the value "Hello, World!"

msgHello.displayMessage();

This statement invokes or executes the displayMessage() method. Recall that when we defined the MyMessage class, we included a method called displayMessage(). This method contains a println() statement that prints the contents of the message attribute to the screen. The msgHello variable is referring to an instance of MyMessage, so when we execute it in this statement, it retrieves the value in the message attribute for this object and displays it on the screen.

Compile and run this program (fix any errors if necessary, and recompile until you compile successfully). You should see the message "Hello, World!" on the screen.

What's the difference between a simple program that prints "Hello, World!" and the MyMessage/TestMyMessage set of files? ome differences are obvious, such as the code statements each source file contains, and the fact that TestMyMessage requires the class MyMessage in order to work. More importantly, today we've written an object-oriented program. Recall that the difference between a program and a class is that a class models an object and a program does not model objects. Programs are often needed to perform simple tasks , or to instantiate objects and program with them (such as we did in TestMyMessage). It is very important to understand this difference!

Is it better to write a program that displays messages with a program such as we did in the first week of class, or with a class, such as MyMessage? It all depends on the context. These are just simple examples, but a large program that manages payroll for a company will very likely have classes for all the major elements and objects in the system (e.g. Employee, Paycheck, Timesheet) and then a program that works with the various objects and invokes their methods.

Exercises

What happens if you move the third statement above the second statement, like this:

public class TestMyMessage {
	
    public static void main(String[] args) {

        MyMessage msgHello = new MyMessage();
        msgHello.displayMessage();
        msgHello.message = "Hello, World!";
    }
}

What happens if you put that same statement above the first statement like this:

public class TestMyMessage {
	
    public static void main(String[] args) {

        msgHello.displayMessage();
        MyMessage msgHello = new MyMessage();
        msgHello.message = "Hello, World!";
    }
}

Modify the TestMyMessage program by creating a second MyMessage object called msgJava. Give msgJava's message attribute the text "I like learning Java.", then display msgJava's message on the screen.

Exercises

[solutions]

1. If each of the following items below were a class, what properties and methods might that class have, and what would sample objects be?

2. Write a class called Room that models a simple, rectangular-shaped room. A room object has:

Write a test program that creates a Room object, then assigns a length and width. Show the room's dimensions and area on the screen.

3. Write a class called Square that models a basic Square shape:

Class: Square
Data:
double side
Methods:
double calcArea()
double calcPerimeter()
String toString()

The toString() method is actually a special method that's already part of Java. We'll learn more about toString() and where it comes from in a later class. For the Square class, the toString() method builds a formatted String that represents the Square, for example, as:

Square: x.x by x.x

Where x.x is the side value, formatted to 1 decimal point. The toString() method should return this formatted String value.

Write a test class to test the square: