Lab 9 In-Class:
Writing Classes
Lab Objectives
- Gain experience writing a class and using the class in a client
program.
|
Log onto the Linux system and create a lab9 subdirectory of
your cs120/Labs
directory for today's work. As usual, you will need to have three
windows open:
an xterm, Emacs, and Firefox.
Writing Classes: The Account Class
Program Account.java contains the
Account class from the pre-lab and pages 193-194 from the textbook.
- In the Account class (Account.java) do the following:
- Fill in the declaration/initialization of the constant for the
$10.00 fee (after the RATE constant - below the comment).
- Fill in the body for methods chargeFee and
setName.
- Updating the documentation: It is very important that methods
in a class be well documented so that programmers understand what they
do and can use them properly. Every method should have documentation
just before the method that describes what the method does, the
parameters the method takes, and any values the method returns.
Currently the comments before the chargeFee and setName methods just
give you instructions. Delete those instructions and add appropriate
documentation to each method.
Make sure your class has no compile-time errors by going to your xterm
window and compiling Account.java.
- Program ManageAccounts.java contains
the shell of the program from the prelab that uses the Account class to
create and manipulate bank accounts using methods from the Account class.
Add code as indicated by the comments.
Note that this program asks you to use getBalance
to print the balance in two places that were not in the prelab and it
has added some interactive input (and asks you to add statements to
deposit and withdraw amounts entered).
Compile and run your program to make sure it works.
- Although chargeFee returns the new balance, your ManageAccounts program
currently does not save or use that new balance, it basically
throws that value away.
Modify ManageAccounts so that each time it
calls chargeFee it stores the returned balance in a variable (you'll have
to declare a new one). After each call to chargeFee, add a print statement
that prints the stored value of the new balance (appropriately labeled).
- Real bank accounts have many more attributes than the three
in this simple Account class. For example, a record of each transaction
would be associated with each account. That is too complicated for us
but we can keep track of the number of transactions. To do this add
the following to the Account class:
- Add an instance variable named numTransactions of type int.
Remember that we make instance variables private.
- In the constructor, initialize numTransactions to 0. (NOTE: Java
automatically initializes instance variables to 0 but it is generally
a good idea to explicitly assign initial values.)
- In the deposit and withdraw methods increment numTransactions. Note
that this should be done only when the transaction actually occurs, not
when there is an error (such as a negative amount or insufficient funds).
- In the toString method modify the string returned to include
the number of transactions, appropriately labeled.
- Classes often have accessor methods for each attribute
(see page 175-180 of the text). These methods are often called
"get" methods or "getters." All they do is return the value of the
attribute so the client program can use it in some way (print it
or use it in a calculation for example).
The getBalance method is an example
of an accessor method. We need to add a getTransactions
accessor method to the
Account class (note this goes in Account.java). It will be similar
to getBalance except it will return the number of transactions.
Think about what the return type for the method needs to be.
Be sure to add the header documentation (comments) for the method.
- Add a print statement at the end of the ManageAccounts
program to print out the number of transactions for each account
(use your accessor method). NOTE: Add this even though you are already
printing the complete account information - this time you should
print just the number of transactions using getTransactions.
- Add an accessor method getName()
to the Account class. Include the header documentation.
- Modify the last print statements (in ManageAccounts.java -
the ones that printed the number of
transactions) to also print the name of the account
owner using the getName method in your print statement.
- Run your program to test it.
- Make sure both Account.java and ManageAccounts.java are indented properly (CTRL-x CTRL-p followed
by CTRL-ALT-\) then print them.
Writing Classes: A Student Class
Program Student.java contains the
incomplete Student class declaration from the prelab.
- Complete the class declaration. You will need to do the
following:
- Declare the
instance data (name, score for test1, and score for test2).
Remember that these should be private.
- Add the bodies for the constructor and the setTestScore method.
- Add the headers and bodies for the getName, averageScore,
highestScore, and letterGrade methods.
Compile Student.java to make sure your Student class has no compilation errors.
- Program Grades.java contains a shell
of a program that contains a sentinel controlled loop (stops when
the name read in is "q") that reads in
the name and two test scores for each student
a class and, for each student, prints the average grade,
the corresponding letter grade, and the highest grade. It will also
compute and print the class average (the average of the student
test averages). All of this will be done using
a Student object and methods from the student class. Fill in statements
in Grades.java to do the following for each student (use the comments in the
code to determine where to put these - note that some of what you need to
do is similar to what you did in pre-lab).
- Declare and initialize any variables needed to compute the class
average (the average of the students' test averages).
- Instantiate a Student object using the name you read in.
- Prompt for and read in the first student's score on test 1.
Use setTestScore to set the test score for the student object.
Repeat this for the score on the second test.
- Notice that after you read in and set the second test score,
there is code to read an end of line character.
This is to solve a problem of using nextLine to read in the
names. After you
read numeric data using nextInt or nextDouble the file pointer
is at the next character in the input stream which will be the
end of line character. If the next thing you do is use nextLine
the only thing that will be read is that end of line. So the
code has a scan.nextLine() to read the end of line in
preparation for reading in the next name (which you do later).
- Use the averageScore
method to find the student's test average and the letterGrade method
to find the corresponding letter grade.
Print this average and letter grade
with a simple label including the name, e.g.,
"Susie's Average is 87.5 which is a B". Use the getName method for the name.
- Use the highestScore method to find and print the student's
highest test score.
- Update the variables for computing the class average.
- Add code to update the loop control variable name - that is, prompt
for and read in the next name (or q to quit). Use nextLine to read in
the name.
- After the loop print out the class average, appropriately labeled.
- Thoroughly test your program.
- Enhance your Student class so that you figure out the student's
initials. Initials are easy to extract from the full name if we
assume there is exactly one space separating the parts of
the full name. All we need to do is use
the first character plus any character that comes after a space.
Proceed as follows:
- First add an instance variable
of type String called
initials to the Student class. This will go with the
variables that hold the name and test scores, and will also be private.
- In the constructor, after you store the name that is passed in,
extract the initials and store them in the initials variable:
- Now add a getter method getInitials to the Student
class that returns
the student's initials. It will just return the value of the initials
variable, which was determined in the constructor.
It should NOT print anything -- it should just
return a string containing the initials.
- Modify Grades.java so that after printing the average for
each student, it prints the student's initials.
- You'll find that the initials come out in lower or upper case,
depending on how the user entered the name.
Modify the code in your constructor
so that the initials are always upper case.
This is easy; construct the initials string as before,
then use the toUpperCase method of the String class.
- Add code to the Grades program to determine who
has the highest average and who has the lowest. Notice that there
are already two Student objects (topStudent and bottomStudent) declared
for this. One (topStudent) has been instantiated with an empty name.
You need to do the following:
- Instantiate bottomStudent as a Student object with an empty name
(just "").
- Declare variables to keep track of the highest and lowest average
and initialize them appropriately before the while loop.
- Inside the loop update the variables for highest and lowest
average AND keep track of which student currently has the highest and lowest.
For example if the current student has a higher average than the
highest so far assign topStudent to be this student (and of course
update the highest average). The same idea applies for the lowest.
- Add statements to the end of
your Grades program that print the values of your
topStudent and bottomStudent variables directly, e.g.:
System.out.println("The student with the highest average is: " + topStudent);
This should run, but notice what it does -- nothing
very useful! When an object is printed, Java looks for a toString
method for that object. This method must have no parameters and must return
a string (there is one in the Account class).
If such a method exists for this object, it is
called automatically -- you don't have to write the call in your program --
and the string it returns
is printed. If no such method exists, a unique hexadecimal
identifier for the object
is printed (e.g., Student@3a56d7).
- Add a toString method to your Student class (in Student.java)
that returns a string
containing the student's name and test scores in the following format:
Joe Test 1: 85 Test 2: 91
Note that the toString method does not call System.out.println -- it just
returns a string. The Die class, the Account class, and the Coin class
in your textbook all have toString methods. The header is the same for
all - the only difference is in the string returned.
You shouldn't have to
change the Grades program -- you don't have to call toString explicitly.
Now see what happens when you run the Grades program - the output is
much nicer!
- Be sure to add documentation for the toString method - state
what it does and what it returns.
- Print Student.java and Grades.java.
Hand In
- The four files (Accounts.java, ManageAccounts.java, Student.java,
and Grades.java).
- Create a zip file of your directory (with both partner's
name) and submit it to Inquire