Lab 7: Enumerated Types¶
Instructions
Answer the following questions one at a time. After answering each question, check your answer before proceeding to the next question.
Save the following file in your lib/
folder:
Save the following files in src/labs/lab07
:
Acknowledgment
This lab was written by Prof. David Bernstein. The original version is here.
Background Material¶
For this lab, you are going to be working with Air Quality Indexes as they are defined by the U.S. Environmental Protection Agency (EPA). You don't need to know much about them, other than the information that is summarized in the following table.
Category | Min | Max | Description | Color (R, G, B) |
---|---|---|---|---|
GOOD | 0 | 50 | Good | Green (0, 228, 0) |
MODERATE | 51 | 100 | Moderate | Yellow (255, 255, 0) |
SENSITIVE | 101 | 150 | Unhealthy for Sensitive Groups | Orange (255, 126, 0) |
UNHEALTHY | 151 | 200 | Unhealthy | Red (255, 0, 0) |
VERY_UNHEALTHY | 201 | 300 | Very Unhealthy | Purple (153, 0, 76) |
HAZARDOUS | 301 | 500 | Hazardous | Maroon (126, 0, 35) |
Motivation and Review¶
To motivate the need for enumerated types, in this part of the lab you are going to construct a small application that makes use of the Announcement
class to display air quality information.
-
Briefly review
ShowAQI.java
. -
Based on your review of
ShowAQI
, what is required to execute it "properly"?Answer
It needs to be given a command-line parameter.
-
Execute
ShowAQI
using what you know is required to execute it "properly". What happened?Answer
A window like the following appeared.
How to run
ShowAQI
with a command-line parameter?Step 1: Open
src/labs/lab07/ShowAQI.java
in VS Code and press F5 to run the program. This will launch a Terminal window. In the Terminal output, you will see two sections: The command executed to runShowAQI
, and the program output, which displays:Usage: java ShowAQI aqi
.Step 2: Press the Up arrow key on your keyboard to recall the previous command used to run
ShowAQI
. Then, add a space followed by the desired command-line argument. Finally, press Enter to execute the command.An easier way to run
ShowAQI
without pressing F5Alternatively, you can type the command yourself (without any extra junk from VS Code):
OS Command Linux / macOS java -cp "bin:lib/*" labs.lab07.ShowAQI 50
Windows java -cp "bin;lib\*" labs.lab07.ShowAQI 50
Explanation:
java
is the command for running a Java application-cp
stands for classpath, which tells Java where to find.class
and.jar
fileslabs.lab07.ShowAQI
is the fully-qualified name (including package) of the main class to run50
(or any other number) is the command-line argument passed to theargs
parameter ofmain()
-
Review the source code for
ShowAQI
. Why did the window have the color and text that it did?Answer
Because the
findColor()
method always returns yellow, and thefindDescription()
method always returns "Moderate". -
Why are the
findColor()
andfindDescription()
methods static?Answer
Because they are going to be called from a static context, specifically the
main()
method. Sincemain()
is static (and will be called without reference to aShowAQI
object), every method/attribute in theShowAQI
class thatmain()
calls/uses must also be static. -
Why don't they need to be called as
ShowAQI.findColor()
andShowAQI.findDescription()
?Answer
Because they, and
main()
, are all in theShowAQI
class. -
Modify the
findColor()
method so that it returns the appropriateColor
object. To save time, only consider the first three categories, and treat SENSITIVE as the default. (Don't be fancy – just use nestedif
statements or aswitch
statement and hard-code the ranges.)Answer
private static Color findColor(int aqi) { Color result; if ((aqi >= 0) && (aqi <= 50)) { result = new Color(0, 228, 0); } else if ((aqi >= 51) && (aqi <= 100)) { result = new Color(255, 255, 0); } else { result = new Color(255, 126, 0); } return result; }
-
Modify the
findDescription()
method so that it returns the appropriateString
object. Again, to save time, only consider the first three categories, treatSENSITIVE
as the default, and don't be fancy.Answer
private static String findDescription(int aqi) { String result; if ((aqi >= 0) && (aqi <= 50)) { result = "Good"; } else if ((aqi >= 51) && (aqi <= 100)) { result = "Moderate"; } else { result = "Unhealthy for Sensitive Groups"; } return result; }
-
If you were a system tester (not a unit tester) who had been tasked with building a complete system test suite, what information would you use to identify important test cases?
Answer
The table that was included in the background material.
-
Would this be black-box or white-box testing?
Answer
It would be black-box testing because the tester would not have access to the source code.
-
Conduct a few system tests to see if your application is working. Don't be comprehensive.
-
The design of the
ShowAQI
application is not very good. For one thing, theShowAQI
class is not cohesive (i.e., it does too many different kinds of things). For another, the implementations offindColor()
andfindDescription()
contain duplicate code. How can these two problems be solved?Answer
The second problem can be solved by creating a class named
AirQuality
that contains both aColor
and aString
(as well as theint
AQI). That way, one method could "find" and return both at the same time.The first problem can be solved by moving the "find" functionality to the
AirQuality
class. This would make theShowAQI
class much more cohesive. -
In the "real world", how many different
AirQuality
objects are there?Answer
Six, one for each category in the table above.
-
Given your answer to the previous question, should
AirQuality
be aclass
or anenum
? In other words, do we need an intensive definition or an extensive definition of the set ofAirQuality
objects?Answer
Since there are only six possible
AirQuality
objects, the right thing to do is just list them all (i.e., use an extensive definition). In other words,AirQuality
should be anenum
.
An Initial Encapsulation¶
This part of the lab will get you started designing and implementing enumerated types.
-
Review the
AirQuality
enum. How many differentAirQuality
objects are there?Answer
As expected, six.
-
Why is the constructor private?
Answer
So that "nobody else" can create an
AirQuality
object (since, after all, there can only be six). -
How many different attributes does each
AirQuality
object have?Answer
Four: a description, a color, a minimum AQI value, and a maximum AQI value.
-
Add accessors for the color and description.
Answer
/** * Get the color associated with this AirQuality object. * * @return The Color */ public Color getColor() { return color; } /** * Get the description associated with this AirQuality object. * * @return The description */ public String getDescription() { return description; }
-
Add a
boolean contains(int aqi)
method toAirQuality
that returnstrue
ifaqi
is in the interval [min
,max
] andfalse
otherwise. Do not use anif
statement, aswitch
statement, ternary operator, or local variables!Answer
/** * Determine whether a given AQI is within the range of this AirQuality object. * * @return true if the AQI is in [min, max]; false otherwise */ public boolean contains(int aqi) { return ((aqi >= min) && (aqi <= max)); }
-
Replace the
Color findColor(int aqi)
andString findDescription(int aqi)
methods in theShowAQI
class with aAirQuality findAirQuality(int aqi)
method. Again, limit your implementation to the first three categories. However, this time, don't use hard-coded ranges. Instead, use thecontains()
method in theAirQuality
enum.Answer
/** * Find the AirQuality object associated with a particular * air quality index (AQI). * * @param aqi The air quality index * @return The associated AirQuality */ private static AirQuality findAirQuality(int aqi) { AirQuality result; if (AirQuality.GOOD.contains(aqi)) { result = AirQuality.GOOD; } else if (AirQuality.MODERATE.contains(aqi)) { result = AirQuality.MODERATE; } else { result = AirQuality.SENSITIVE; } return result; }
-
Modify the
main()
method of theShowAQI
class so that it uses thefindAirQuality()
method.Answer
/** * The entry-point of the application. * * @param args The command-line arguments */ public static void main(String[] args) { AirQuality quality; Announcement announcement; int aqi; if ((args == null) || (args.length < 1)) { System.out.println("\nUsage: java ShowAQI aqi\n"); } else { aqi = Integer.parseInt(args[0]); quality = findAirQuality(aqi); if (quality == null) { System.out.println("\nInvalid AQI. Please try again.\n"); } else { announcement = new Announcement(quality.getDescription(), quality.getColor()); announcement.setVisible(true); } } }
-
Test the modified
ShowAQI
. -
Is
ShowAQI
cohesive?Answer
Not yet.
An Improved Encapsulation¶
This part of the lab will help you understand why and how to build functionality into enumerated types.
-
Move the
findAirQuality()
method from theShowAQI
class to theAirQuality
enum. (Note: You will have to change the visibility topublic
.) -
Why is the
findAirQuality()
method static?Answer
Because it is going to be used to find an
AirQuality
object. If it weren't static, we would need anAirQuality
object before we could call it. -
Modify the
ShowAQI
class so that it uses thefindAirQuality()
method in theAirQuality
class.Answer
quality = AirQuality.findAirQuality(aqi);
-
Why do you now need to include the class name in the call to the method?
Answer
Because
findAirQuality()
is in theAirQuality
class and this statement is in theShowAQI
class. -
Test the modified
ShowAQI
. -
Is the
ShowAQI
class cohesive?Answer
Yes. It now does one thing – it shows air quality information.
-
Is the
findAirQuality()
method in theAirQuality
class complete?Answer
No, it only works for three of the six
AirQuality
objects. -
Given that there are only six different
AirQuality
objects, how long would it take to add the other three cases?Answer
A minute or two.
-
Suppose there were 100 different
AirQuality
objects, how long would it take to add the other 97 cases?Answer
It would take some time, and it would be annoying.
-
Suppose an
AirQuality
need to be added to theenum
three years from now. How likely is it that you will remember to also modify thefindAirQuality()
method?Answer
Very unlikely!
-
Use the
values()
method and a traditionalfor
loop to fully-implement thefindAirQuality()
method. (Returnnull
if the if theaqi
is out of bounds.)Answer
/** * Find the AirQuality object associated with a particular * air quality index (AQI). * * @param aqi The air quality index * @return The associated AirQuality */ public static AirQuality findAirQuality(int aqi) { AirQuality[] all; all = AirQuality.values(); for (int i=0; i<all.length; i++) { if (all[i].contains(aqi)) { return all[i]; } } return null; }
-
Test the modified
ShowAQI
.
Submission¶
- Submit only
AirQuality.java
andShowAQI.java
to Gradescope. - Answer the questions in Canvas for your section's Lab 7 assignment based on this lab.