/* --- CSU213 Spring 2006 Lecture Notes --------- Copyright 2006 Viera K. Proulx Lecture 2: Happy Unions */ /* Goals: - recall data definitions for unions from HtDP - translate data definitions into class diagrams and Java code - understand that the concepts are the same A restaurant would like to make a computerized menu listing to advertise on the web. They asked us to design the data representation of their menu information. We start by asking questions --- analyzing the problem and identifying the relevant information: What kinds of food ddo you offer? -- We have appetizers, soups, salads, and main dishes later we may add more (deserts, drinks, etc., but let us start here. How do you describe an appetizer? -- Just the name is fine. Can you give me some examples? -- Mozarella sticks, Egg roll. What about soups? -- Well, they can order either a bowl of soup or just a cup of soup and. of course, they have to say what flavor. So, the examples would be a cup of tomato soup or a bowl of clam chowder? -- Yes, that's right. OK - what choices do the diners have when ordering a salad? -- They need to tell us the kind of salad (Greek, Garden) and they need to choose the dressing (Ranch, Italian, Blue cheese). You are catching on - I need not only the description of the needed information, but also some examples. What about the main dishes? -- Well, we would like to list them in three categories: meat dishes, vegetarian dishes, and fish dishes. Let's start with the meat dishes. What choices do the diners have? -- They choose the dish, such as roast duck or steak and two vegetables. How about the vegetarian dishes? -- These just have a name, but we aslo label them wehther or not they are vegan. And the fish dishes? -- These are special - there are no options. So you may get a broiled salmon with asparagus and rice. Do you have some deals on when the diner orders the whole dinner? -- Yes, they can order one of appetizer or soup or salad, and one main dish for a fixed price - but we do not worry about prices yet. Thank you. I think we are ready to design the classes. Let us see what we would do in Scheme: ;; A FirstCourse is one of ;; -- Appetizer ;; -- Soup ;; -- Salad An Appetizer is a String ;; A Soup is (make-soup String Boolean) (define-struct soup (name cup)) ;; A Salad is (make-salad String String) (define-struct salad (name dressing)) That means, in Java will have a class for each of the three first courses: appetizers soups, and salads: +-------------+ +-------------+ +-----------------+ | Appetizer | | Soup | | Salad | +-------------+ +-------------+ +-----------------+ | String name | | String name | | String name | +-------------+ | boolean cup | | String dressing | +-------------+ +-----------------+ But now we need a clas to represent any one of the first meals. To do this, we use a 'union'. We define a commoon type for all three classes (an interface) and indicate in the class definition that each of these three classes is of the same type. First we draw a picture: +-----------------------+ | interface FirstCourse | +-----------------------+ ^ | | - - - - - - - - - - - - - - - - - - - - | | | | | | +-------------+ +-------------+ +-----------------+ | Appetizer | | Soup | | Salad | +-------------+ +-------------+ +-----------------+ | String name | | String name | | String name | +-------------+ | boolean cup | | String dressing | +-------------+ +-----------------+ Here is how we represent this in terms of Java classes and interfaces: */ interface FirstCourse{} class Appetizer implements FirstCourse { String name; Appetizer(String name) { this.name = name; } } class Salad implements FirstCourse { String name; String dressing; Salad(String name, String dressing) { this.name = name; this.dressing = dressing; } } class Soup implements FirstCourse { String name; boolean cup; Soup(String name, boolean cup) { this.name = name; this.cup = cup; } } /* Of course, we now have to make data examples of the different pieces of information we are trying to represent: We group them all in a class named Examples: */ class Examples { Examples() {} FirstCourse ms = new Appetizer("Mozarella sticks"); FirstCourse er = new Appetizer("Egg roll"); FirstCourse ts = new Soup("Tomato", true); FirstCourse cc = new Soup("Clam Chowder", false); FirstCourse gSbC = new Salad("Garden", "Blue cheese"); } /* The Examples class is the place where we show how the information is represented as data, and later, we will be testing our programs there. The structure is a bit different from the simple classes we have seen. The constructor takes no arguments, as seen by just empty parentheses () --- and does not initialize any fields, as seen by the empty brackets {}. That is because all fields are initialized to the same value every time we create a new instance of the Examples class. These fields represent our sample data. To see the values of these data items we need to do two things in the Interactions window, after we run the program: -- create an instance of the Examples class: > Examples e = new Examples(); -- observe the values represented by this instance: > e This will result in seeing: Examples( ms = Appetizer( name = "Mozarella sticks"), er = Appetizer( name = "Egg roll"), ts = Soup( name = "Tomato", cup = true), cc = Soup( name = "Clam Chowder", cup = false), gSbC = Salad( name = "Garden", dressing = "Blue cheese")) The Interactions window shows us in a humanly readable form the values of all fields. We can examine the individual fields within the instance of the Examples class as follows. To see the value of the field gSbC within the instance e, we write: >e.gSbC and see Salad( name = "Garden", dressing = "Blue cheese") as the result. One more comment about the data definitions. We declare the type of the field gSbC to be FirstCourse. That means its value can be an instance of any class that implements the FirstCourse interface and it can be used anywhere where the program expects a piece of data of the type FirstCourse. We then initialize the field by giving it a specific value - this value must be an instance of a class - as there are no instances of interfaces. And, of course, it must be an instance of a class that implements the FirstCourse interface. We now look at the main dishes. Again we have three different kinds, each represented by it own class. In Scheme the data definition would be: ;; A MainDish is one of ;; -- MeatDish ;; -- Vegetarian ;; -- FishDish An MeatDish is a (make-meatdish String String String) (define-struct meatdish (name veg1 veg2)) ;; A vegetarian is (make-vegdish String Boolean) (define-struct vegdish (name vegan)) ;; A FishDish is (make-fishdish String) (define-struct fishdish (name)) Make examples of the dishes we discusses earlier. Of course, this translates into three Java classes: +-------------+ +---------------+ +-----------------+ | MeatDish | | Vegetarian | | FishDish | +-------------+ +---------------+ +-----------------+ | String name | | String name | | String name | | String veg1 | | boolean vegan | +-----------------+ | String veg2 | +---------------+ +-------------+ We leave it up to you to finish. You need to define a common interface to these three classes, and then translate our earlier examples of information into data --- instances of these three classes. Finally, a dinner order consists of the first course and the second course. Design the class to represent a dinner and make two examples of your favorite meals. Interpret the data --- the instances of this new Meal class --- as information, i.e. write an English sentence that explains what did you order. */