Assignment 2: Creating and Using Our Own Classes
Objectives:
- Debugging and creating basic Java class
- Overriding inherited instance methods
- Using a class you wrote in another class
- Writing Static Methods
Due: Wednesday before class.
Recommendation: Complete the first two parts before Friday's class, complete part 3 before Monday's class.
Set Up
Cloning the Repository
In your terminal, go to the directory where you are keeping your repositories for CSCI209. Clone the repository for this assignment.
Part 1: Fixing A Program (40)
Debug3.java
contains at least 5 errors. Some are
compiler errors that the compiler will catch. Others are logic errors
that you need to catch. One is an access modifier error that is
not good OO style.
Comment out the original code and explain the cause of the error. Then, correct the code. Make as few changes as necessary to fix the code.
After you're sure the program behaves correctly, save the output in
a file called debugged.out
. Add the file to
your repository.
Part 2: Creating a Birthday Class (30)
Overview: Create a Birthday
(but not
birth date) class. You will write this class from scratch, so
remember to add it to your repository.
- The state of the class should be the
month
andday
. - There will be one constructor for
the
Birthday
class. The constructor will take as parameters the month and date. - The methods of the class should be getting and setting the month and date.
- Pay close attention to the access modifiers you use for the state and methods.
- The
main
method for the class should test yourBirthday
class. Don't just run the program a bunch of times, changing the code and recompiling and running. Have all the tester code in this method. See theChicken
class as an example.
This problem is underspecified, e.g., I'm not saying how to represent the month and day. I'm leaving that up to you.
This problem should be as simple as it seems (no input, no application, no error handling). Focus on writing good, solid, well-commented (JavaDocs!), and well-tested code.
The problem doesn't seem like one of my normal problems because it isn't. We're building to something.
This is a good time to commit and push your code.
Part 3: Overriding Methods (25)
Add appropriate toString
and equals
methods. Use the appropriate signature for each method, i.e., the
same as the parent class's.
toString
For the toString
method, consider what you would
expect to be displayed when you print out the birthday object. Like,
when you run System.out.println(birthday);
, what would
you expect to see?
equals
You will probably be tempted to have a Birthday
object
as a parameter to the equals
method you're implementing.
However, the parameter should be an Object
object, to
match the parent Object
class's method.
Follow the procedure below for implementing the equals
method:
- Use the == operator to check if the argument is a reference to this object. (If the variables are references to the same object, they're clearly equal!)
- Use the
instanceof
operator to check if the argument has the correct type. (Note: if a variable is a null reference, theninstanceof
will befalse
, so we don't need to check if the other object is null separately.) - Cast the argument to the correct type.
- For each "significant" field in the class, check if that field
of the argument matches the corresponding field of this object.
Note: for doubles, use
Double.compare
and for floats useFloat.compare
Source: Effective Java
Testing
As always, test your methods appropriately in the main
method.
Part 4: Overloading Constructors (25)
Add a new constructor for the Birthday
class. This
constructor takes no parameters and randomly generates the
birthday (the month and date).
For this assignment, assume that February has 29 days.
Also, you want only one random
number generator object for the whole Birthday
class to
ensure the best random number generation. (We can debate about whether
a uniform distribution
across months is the correct way to generate birthdays, but for
simplicity, that is our assumption.) Note that having one random number
generator object does not mean that you are only generating one
random number: one generator can generate many random numbers.
You may want to create a static, final
array of integers representing the number of days in each month.
(Why?)
Test by creating at least one object using this constructor and calling some methods on it. (Why would it be beneficial to create more than one object?) It is harder to automatically test randomly generated birthdays. However, there are some constraints on birthdays that you could check. You could argue that "I wrote the class to not violate the constraints", but maybe you only thought you did. Please test to help verify the correctess of your code before I find errors or you find errors later, when you have more code and it makes finding bugs more difficult.
Save the output from all your tests in birthday.out
.
Part 5: Using the Birthday Class to Model the Birthday Paradox
Are you familiar with the birthday paradox? In a group of 23 randomly chosen people, there is more than 50% probability that some pair of them will both have been born on the same day. For 57 people, the probability is more than 99%.
Write a Java class named BirthdayParadox
(separate from
the Birthday
class) that runs an experiment that
tests/verifies these probabilities.
Since Birthday.java
and BirthdayParadox.java
are in the same directory,
BirthdayParadox.java
does not need to
import Birthday
.
For a set of people with randomly generated birthdays, determine if any of them have the same birthday. Because there is randomness involved, you need to run the experiment several times, each time with a new set of people with randomly generated birthdays. (30 is usually the magic number of experiments, but when you're first testing, you'll want to perform fewer experiments.)
Run the experiment with different numbers of people: from 5 to 100 people, in 5-person increments.
Note that a positive trial means that there was at least one pair of people with the same birthday. There could be more than one pair with the same birthday in a trial, but that only counts as one positive trial.
Stop here.
Start thinking about what methods/functionality would be
helpful in implementing the solution. How can you break this problem
into smaller, easily testable pieces? If you don't break the problem
into small, testable parts, you will undoubtedly struggle because you're
trying to do too much at once and you're new to Java. While people tend
to want to complete what they know how to do first, consider
implementing some of the harder subproblems first so you can focus on
testing and debugging them. Build from there.
For example, once you have a subproblem solved, you may want to put that
part into a method that you can call/reuse.
Print out the results of your experiment in a table, as shown below. Show the number of people, the number of trials, the number of positive trials, and the percent of positive trials.
You can
use String.format
or the printf
method of System.out
.
(References
for Formatter
,
which talks in detail about the format specifiers;
for printf
: Colorado
State
and Baeldung.)
Example output:
# People # Trials # Positive Pct -------- -------- ---------- ------ 5 10 1 10.0 10 10 1 10.0 15 10 2 20.0 20 10 4 40.0 25 10 6 60.0 30 10 7 70.0 35 10 5 50.0 40 10 9 90.0 45 10 10 100.0 50 10 10 100.0 55 10 10 100.0 60 10 10 100.0 65 10 10 100.0 70 10 10 100.0 75 10 10 100.0 80 10 10 100.0 85 10 10 100.0 90 10 10 100.0 95 10 10 100.0 100 10 10 100.0
# People # Trials # Positive Pct -------- -------- ---------- ----- 5 30 1 3.3 10 30 5 16.7 15 30 8 26.7 20 30 12 40.0 25 30 17 56.7 30 30 21 70.0 35 30 23 76.7 40 30 27 90.0 45 30 30 100.0 50 30 27 90.0 55 30 30 100.0 60 30 30 100.0 65 30 30 100.0 70 30 30 100.0 75 30 30 100.0 80 30 30 100.0 85 30 30 100.0 90 30 30 100.0 95 30 30 100.0 100 30 30 100.0
In the above table, # Positive
is the number of times
at least two people had the same birthday out of all the times the
experiment was run.
Note: your new Java class should "see" your
Birthday
class if you used the public
keyword before class
in Birthday.java
and if
the two .class
files are in the same directory.
Use good program organization, e.g., write methods to make your code easier to read/understand.
Save the output from one run of your program using 30 trials in a
file named paradox.out
. Add the file to your
repository.
Students sometimes get overwhelmed by this problem. It is important that you break it into small steps to make sure that it works, then move on to the next part. Recall good development processes.
Testing the BirthdayParadox is hard to do programmatically. (Why?) You'll most likely need to return to your 111/112 practices of implementing smaller parts, printing out intermediate output, and checking the results, manually.
Extra Credit (4 pts)
Have your program take as a command-line argument the number of trials to perform. If the command-line argument is not given, default to 30 experiments. You may find Java's Integer class helpful.
Submission
As usual, put all of your code and output files in your GitHub repository that both you and I can access.
Grading (200 pts)
You will be evaluated based on
- (40 pts) Part 1: Catch, fix, explain all errors; output file
- (30 pts) Part 2: Correctness of your program (e.g., no compiler or runtime errors, matches specification)
- (25 pts) Part 3: Extending Birthday class
- (25 pts) Part 4: Extending Birthday class; output file
- (65 pts) Part 5: Birthday Paradox; output file
- (15 pts) Parts 1--4: Proper style, indentation, documentation of Java programs