CS 302 Lab 6

Lab 6: Developing an Instantiable Class: Candidates

CS302, UW-Madison

Today We'll be:

Overview

You've learned how to organize a program's statements into task-oriented modules using methods. You've also learned how to organize data into lists and tables using arrays. The next step for organizing programs is to combine data and methods into a single module, called an instantiable class, which is one of the key ideas of object-oriented programming (OOP)!

Instantiable classes are used to represent "objects" that are typically more complex than just a number, character, or other primitive type. They usually are a composite of primitive types and objects from other classes. An example would be the String class, which we've use to create string objects so our programs can work with sequences of characters such as words or phrases. We say that each string object is an instance of the String class. Each instance has some data, which is stored in instance variables, and can do operations on their data by calling instance methods. You'll hear OO programmers interchangeably use the terms objects and instances.

Java provides many instantiable classes in its API (e.g., String, Scanner, Random, ArrayList), but our goal is to make our own. Today, you'll be coding an instantiable class to represent a candidate seeking an elected office. When designing instantiable classes, there are two key questions you'll want to answer:

In this lab, you'll be creating the Candidate instantiable class, which we'll tell you how to design. You'll incrementally develop it and then use your instantiable class in a small application.

Getting Started

Begin by creating a new project in Eclipse named CandidateLab, and then download and add to your project the following files:

You'll be modifying both files so be careful to note which class name we refer to in the tasks below.

Task 1: Instance Variables - Stuff to Store

Let's start with the first question. What information do we want to store about candidates? There are many things we could store, but let's just store the following:

Once you've decided what to store you'll need to make some coding decisions:

We've already added to the Candidate class the instance variable, name, that will store the candidate's name. Note it's a String type and we've made it private as is typically done with instance variables.

Note that the initial value of instance variables will be zero for their type: for ints it is 0, for doubles it is 0.0, for chars it is the null character '\0', for booleans it is false, and for any reference variable it is the null address.

Now do the same for the candidate's political party and office being sought.

Task 2: Mutators and Accessors - Things to Do

Now that we have some stuff that candidate objects can store, we'll want to be able to access and change that information stored in our instance variables. We'll start with two fundamental operations that most instantiable classes provide:

We'll want to be able to access a candidate object's name. We've added an accessor for this purpose. Use it as a basis to code your own accessors for the other two instance variables.

We'll also want to be able to set/change a object's name. We've already provided this code:

public void setName(String name) {
        this.name = name;
}

Note that it looks very similar to the static methods we've been coding. Like them, it has a heading and method body, and it has a return type, method name, and a parameter list. It does NOT have static in the heading, which tells the compiler it's an instance method.

Write a mutator method for the candidate's political party and another for the office being sought.

It is important to note that we typically do not have console input (Scanners) or output (print statements) in the bodies of accessor and mutator methods. Information needed to change the name is passed in via a parameter, and accessing what's in the name is passed out via the method's return value.

Task 3: Using a Driver Class to test Instantiable Classes

Now test the code in your Candidate class using the CandidateTester class that you downloaded. Classes like this that are used to test an instantiable class to ensure they work as expected are called driver or test classes. Run the CandidateTester program to verify that setting and getting a candidate's name works.

Next, take a look at the code in the test class. Note that it creates several candidate objects (aka instances) and calls the instance methods to set and get their names. When calling instance methods the form for is: <objectName>.<methodName>(<arguments>). For instance methods, we need to say which software object we want to do a particular task and then follow that with the method call for the task we want done:

	candidate1.setName(name1);
   candidate2.setName(name2);
   candidate3.setName("Benjamin Franklin");

Try using the form for calling static methods to call an instance method and see what error you get. For example, try adding System.out.println(Candidate.getName()); in the test class.

Next, let's experiment with the name mutator method in the Candidate class by removing the "this." as shown below:

public void setName(String name) {
        name = name;
}

Run the test program class and determine the effect of this change in your code. Why isn't it working as desired?

Note, setName's parameter variable and Candidate's instance variable both use the same identifier, name, which causes an ambiguity. The modified code will not change the instance variable as desired. Instead, it assigns the parameter variable to itself, which is pretty useless. Adding "this." makes it clear to the compiler that we mean (this object's) instance variable (a.k.a. field) gets the reference in the parameter variable. Another way to resolve this problem is to use unique names to avoid the ambiguity in the first place as in:

public void setName(String givenName) {
        name = givenName;
}

One more thing about this. It is a variable that instance methods automatically get. It stores a reference to the calling object, that is, the object that calls the instance method. In the code example above where setName is called by three candidates, this will be set up to have the reference to the correct one for each call, which is how instance methods know which object to use.

Now, give it a try. Add code to your CandidateTester class to test your other accessors and mutators, which you added in the earlier tasks. Run your modified test class to ensure things are working as expected.

Task 4: Enhancing the Candidate Instantiable Class

Adding More Data

At this point your Candidate class stores three strings. Let's enhance this class so that candidate objects also store:

For each additional piece of information you'll need to consider:

Add the code for each new piece of information to your instantiable class. First declare instance variable (make sure to make them private). Then add accessors for each new instance variable but do not add mutators.

Adding More Methods

We'll finish the Candidate class with two more methods that make further use of new information we've just added. The specifications for these methods are:

Make sure to use your test class to test them.

Task 5: Commenting the Basic Candidate Class using the built-in JavaDoc tool.

You've seen the Java API has very useful web pages that document the classes that Java provides. You can easily make your own web pages like Java's for your classes, and we'd like to show you how. First, you'll need to add comments in a specific form to your Candidate class. You'll need to complete the class header comment to your instantiable class and add method header comments to each method in the instantiable class, which are described in the CS302 Commenting Guide. When you're finished commenting your class, here's how you use Eclipse to generate Javadocs:

Now open your newly created documentation in a web browser.

If your web browser has a File -> Open command, can use that. choose "New Tab → File -> Open (or Open File)" and navigate to your Eclipse workspace and the folder location you entered as the destination.

If you don't have a File -> Open command, (Firefox), open a File Explorer (Win) or Finder Window (Mac) and navigate to the doc folder you created.  There will be many files at this location; double-click the file index.html to open the main index to your documenation in your default browser.

Alternatively, some browsers allow you to type the filename explicitly in the web address field. The exact file name varies depending upon your system configuration and project name, but in the CS labs it will be something like this: file:///L:/defaultuser/workspace/lab8/doc/index.html

There will be many files in the doc folder; select the file index.html. You will see a page like those in the Java API, but the classes listed will be the ones you have written. You can click on the links and look at the documentation for your individual classes. If you select one of the files named after one of your classes, you will see only the documentation for that class.

Challenge Task 1: Adding Constructors in Candidate Instantiable Class (Optional)

Our code above relies on the default constructor, which can be dangerous because the objects won't be properly initialized until the appropriate mutator methods are called. A better way is to use constructors. The main purpose of a constructor is to do the appropriate initialization when a new object is created, so that all of the instance variables begin with valid information. When designing constructors you should think about where the initial value for each instance variable comes from. Is it passed into a parameter or should a default value be used?

Add the following two constructors to the Candidate class to initialize candidate objects to:

Make sure to properly comment these constructors and update your Javadocs. Also modify your test class and main class to use these constructors.

Challenge Task 2: Coding a Small Application that uses the Candidate Instantiable Class (Optional)

Write a simple main program that uses your Candidate class. First create a new class within your CandidateLab project called CandidateApp and code its main method to do the following:

  1. Declare a Candidate object.
  2. Allow the user to input values that are used to set up the Candidate object.
  3. Code a loop to allow a user to add contributions to the candidate until the user quits.
  4. Print the candidate's name, party, office, total contributions, and average contribution.