Introduction
Review: More about Classes
Switch Statements
We have already discussed if, if else-if, and if else-if else statements in regards to branching. However, using these may not be the most clean or efficient way to control many cases of a single variable. Switch statements resolve this problem by creating a multi-branch statement that compares a variable to constant values.
Here is the structure of a switch statement:
switch(variable){
case (value1):
break;
case (value2):
break;
case (value3):
break;
default:
break;
}
Cases are separated by break statements, so the compiler knows that if one match is found in the switch statement, no other cases need to be checked or run. When a match is found when comparing the variable to a value in a case, the block of code beneath that case executes.
If break statements are omitted, something called fall through occurs. This means that instead of stopping after executing the code following the case, the program continues into the code in the next case. Break statements can be intentionally omitted, but it is easy to unintentionally create fall through by forgetting or misplacing a break statement, so be sure to include them thoughtfully within your switch statement.
The default case exists at the end of the switch statement, and can be included or omitted. If the program should execute a portion of code if no matches are found within the cases, that code should be included in the default case.
For more detail on switch statements and to see examples, check Zybooks.
Conditional Expressions
To simplify common code, Java supports a shorthand notation of a simple if-else statement.
Conditional expressions have the form:
condition ? expressionWhenTrue : expressionWhenFalse
The ? and : are sometimes referred to as ternary operators. Depending on the truth value of the condition, the conditional expression will perform one of the expressions following the ?.
These conditional expressions are used in good practice only for assignment statements for variables.
Enumerations
Zybooks defines an enumeration type as something that declares a name for a new type, as well as possible values for that type.
When variables may only hold a few different values, then enumerations may come in handy to control data types.
To declare an enumeration:
public enum identifier {enumerator1, enumerator2, ...}
Then, when referring to an enumeration within your code, you must use the following format:
enumerationType.enumerator
Introduction to Lab
Today’s lab will include two classes, Coffee and Order, that can be used to read an order of coffee drinks from a file, and then store them in an object. Important fields like the sizes and types of drinks, as well as the flavors used, are included as class variables in the objects. A barista might find it helpful when getting supplies ready for an order to know what flavors they need, as well as what type of cups they need based on the type of drink.
Review the comments in the two classes, and analyze the functionality of the existing code.
Coffee
is designed to represent a single drink. It contains a constructor, a method to calculate price, two helper methods that assist the Order class, and four class variables.
Order
is designed to represent a collection of multiple coffee drinks, with the Coffee objects stored in an array as a class variable.
There are similar class variables to represent the price, and two major methods, one to read orders from a file and create and store the appropriate Coffee objects, and one to return a helpful message representing info about the Order object.
OrderMain
is the class provided for you to test your code. We have also provided text files order1.txt and order2.txt to download. Test your code with OrderMain before submitting your lab to check for any compilation errors, and to ensure your methods for both Coffee and Order are working as expected.
Step 1 : Order.readOrder(String fileName)
You have worked with reading from files in previous labs. In this lab, you will read from a file in the Order class and its readOrder() method. The name of the file to read from is passed in as a string to the method.
You will be responsible for:
- Creating a Scanner that reads from the file
- Creating a loop that iterates through all lines in the file
- Creating a Coffee object for each line of the file.
- Note that the Coffee constructor takes in a String as a parameter, so to create the Coffee object, you need only to pass the line to the constructor.
We have given you most of the code for the readOrder method, and you will only need to complete the steps above.
You should uncomment the code in the loop now. However, it won’t compile until you complete a few parts in Coffee.java first! You can also stub out the needed parts to test it!
Step 2 : Enumerations in both Order and Coffee
In both the Coffee and Order classes, we will be using two enumerations. Review the explanation above for how to define an enumeration, and define the following in both classes:
- An enumeration called types that has 3 possible values: HOT, ICED, and BLENDED
- An enumeration called sizes that has 3 possible values: SMALL, MEDIUM, and LARGE
All Caps?
While not required, this is often the naming standard for enums.
Step 3 : Coffee Constructor
In the constructor of the Coffee class, create two switch statements that initialize the class variables representing the coffee type and size based on the strings parsed from the string passed to the constructor.
An order line in a file will have the format: [size] [type] [flavors], where size can be “S”, “M”, or “L”, and type can be “H”, “I”, or “B” to represent the respective enumerations.
Based on those string values, assign the class variables type and size to the correct enumeration.
After completing the constructor, call the test method for this step within main to ensure your constructor is working as expected.
Step 4 : Coffee.getSizeIndex() and Coffee.getTypeIndex()
Use a switch statement in the two helper methods in the Coffee class, getSizeIndex() and getTypeIndex().
Both methods return an int based on the parameter, which is either a sizes enumeration or a types enumeration.
The comments above this method describe what enumerations should return what ints, as well as the default values.
After completing the methods, call the test method for this step within main to ensure your methods are working as expected.
Step 5 : Coffee.calculatePrice()
The calculatePrice method uses a switch statement and conditional expressions to assign the price variable for the coffee object.
In this method, you will be creating two more switch statements to assign the price of a coffee drink to the Coffee object’s class variable price.
In the first switch statement, use the size and a conditional expression based on whether the type is blended to assign the price.
Review the explanation on conditional expressions above. The commented portion above this method outlines the pricing details.
The second switch statement should occur within the for loop that iterates through the flavors of a Coffee object. If the flavor is not one of the following: caramel, chocolate, or vanilla, it will add an additional 50 cents to the price. Consider using fall through in your cases to simplify the switch statement.
After completing the method, call the test method for this step within main to ensure your method is working as expected.