> Sample problem solutions > 1. (This is *the* classic exercise in inheritance) > > Suppose we have > > class Base { > public int x; > public Base(int x) { this.x = x; } > public int f() {return x;} > public int g() {return x*x;} > } > > class Deriv extends Base { > private int y; > public Deriv(int x, int y) {super(x); this.y = y;} > public int f() {return x + y;} > public int g() {return 3*super.g()} > } > > (a). Suppose we have the following: > > Base b1 = new Base(4); > Base b2 = new Deriv(4,5); > Deriv d1 = new Deriv(4,6); > > What is the output of the following? > > System.out.println(b1.f()); > System.out.println(b2.f()); > System.out.println(d1.f()); 4 9 // this is the "surprising" one because the compiler thinks b2 is a Base 10 > (b). In class Deriv, the method f returns x+y. This is legal because x is public in Base. > Most likely, however, x would be private in Base. Assuming it was, how would you > change Deriv so that it still compiled, and f() still worked the same way? You would make x private in Base, and then use an accessor to get its value in Deriv. Note that Base.f() returns the value of x, and so can be used as an accessor, allowing Deriv.f to be as follows: public int f() {return super.f() + y; } > (c). What is the output of the following? > > System.out.println(b1.g()); > System.out.println(b2.g()); > System.out.println(d1.g()); Again, we return x*x for Base objects and 3*x*x for objects created as Deriv, regardless of the type of variable in which they're currently stored. 16 48 // = 3*16 48 > ============== > 2. Each of the following situations involves a design problem. > Discuss the problem, and suggest a better design. > > (a). Class CD with methods getTitle, getArtist, getComment, print > Class Video with methods getTitle, getDirector, getComment, print The man problem here is the duplicated code. Inheriting classes CD and Video from a common base class Item, as was done in the DoME example version 2, means that the common code now appears only once (in class Item) rather than in each class separately. It also means that a database *using* these classes can keep just one ArrayList (or whatever) of Items, rather than having separate data structures for each of CD and Video, and duplicated code for those two data structures. > (b). InitSimulator(int n): create simulator and run n generations of simulation It would be better -- more in keeping with good COHESION -- to separate the different functions of initialization and execution: initSimulator() runSimulator(Simulator s, int n); > (c). A class with public data fields Public data fields usually lead to tight coupling between the classes, as one class uses the public data fields of the other and thus prevents the other class from getting a new implememtation. > ============== > 3. You have a HashSet strset. You want to convert to an ArrayList format. > To this end, you create an empty ArrayList > ArrayList strlist = new ArrayList(); > (a). Give a for-each loop that copies each element of strset to strlist. for ( String s : strset) { strlist.add(s); } > (b). Upon reading the javadocs files, you discover two things: > (i). HashSet derives from superclass Collection > (ii).ArrayList has a method addAll(Collection). > Use these facts to copy strset to strlist in one statement. strlist.addAll(strset); > ============= > > 4. Suppose you want to implement the StoneRoom described in the handout, > which behaves as follows: > You have entered a room with a huge stone in the center. > It looks like it might be covering something. > MOVE STONE > You are too weak and hungry to move the stone. > EAT COOKIE > Wow! That made you feel stronger! > MOVE STONE > Filled with a burst of strength, you move the stone. > A moneybag is revealed. > Describe changes that need to be made to getShortDescription, getLongDescription, > getExit and respond. For the last, describe which new command words the respond > method will handle, and when super.respond() is invoked. getShortDesc: yes; description changes (presumably) after you move stone getLongDesc: no changes; no exits or items are concealed getExit no changes respond new responses to: MOVE STONE EAT COOKIE (needs to check inventory) > 5. Do the same as 4, but for the DragonRoom: > GO NORTH > The passage is littered with bones. A dragon's roar splits the air. > I hope you have a weapon! > << go back and GET SWORD...>> > GO NORTH > You have entered the lair of the dragon. His tail flicks behind you > and the exit door latches closed. > GO SOUTH > the dragon won't let you out > ATTACK DRAGON > The dragon is injured! > ATTACK DRAGON > The dragon dies! > GO SOUTH > The passage is littered with bones. > GO NORTH > You have entered the lair of the dragon. > His dead body lies before you. // NOTE DESCRIPTION CHANGE! > Exits: south north > GO NORTH > You have entered the dragon's treasury getShortDesc: yes; description changes after you kill dragon getLongDesc: Not absolutely necessary, though in the above a list of exits was NOT provided while the dragon was still alive. getExit yes; no exits are available until the dragon is dead! respond new responses to: ATTACK DRAGON (needs to check inventory) Note that you have to invoke this TWICE in the example above. An easy way to do that is to have the room keep count in attackCount, initially 0. void respond(Command c, ...) { ... if (commandWord.equals("attack") && ...) { if (attackCount == 0) { attackCount ++; System.out.println("The dragon is injured!"); } else { dragonLives = false; System.out.println("The dragon dies!"); } ... } > 6. Suppose that, in my version of the game presented in class, when you return > Pepe the snake the grateful lab director tells you "from now on, you will be > able to carry twice as much as before", referring to your weight limit for > carrying Items in the game. > > The weight limit would be part of the Game class. Describe the problem we > would have implementing this in the ZooRoom class, and discuss one possible > solution. The problem is simply that, from the ZooRoom class, the Game class is normally inaccessible. This is the same problem we have with the inventory. If we had a variable referring to the current Game object, say g, we could easily manipulate the weightlimit with straightforward accessors and mutators: int Game.getWeightLimit(); void Game.setWeightLimit(int w); One way to get a reference to the Game object is to provide it in the constructor for ZooRoom: ZooRoom(String desc, Game g) { description = desc; theGame = g; } Then you can put the following into ZooRoom.respond: if (commandWord.equals("GIVE") && ... ) { ... System.out.println("from now on you can carry twice as much"); int old_weight = theGame.getWeightLimit(); theGame.setWeightLimit(2*old_weight); } Perhaps a better way is to create a Player class, containing all player info (including inventory and the weight limit), and then pass the current player as parameter to Room.respond() (and thus ZooRoom.respond()). > 7. Suppose we have the following class Rectangle. Derive from it a class Square, > and include the implementation of the constructor. > > class Rectangle { > private int xPos, yPos; > private int height, width; > public Rectangle(int x, int y, int h, int w) { > xPos = x; > yPos = y; > height = h; > width = w; > } > public void draw() {... not shown ...} > public int getX() { return xPos;} // getY() similar > public int getWidth() {return width;} // getHeight similar > } This is all you need: class Square extends Rectangle { public Square(int x, int y, int side) { super(x,y,side,side); } } > (b). Suppose someone now adds a doubleWidth method to Rectangle: > public void doubleWidth() { width = 2*width; } > What problem does this present for your class Square? > Can you think of a way to avoid this? The problem is that adjusting the width means the shape is no longer a square! One approach is to "disable" this by providing an overriding doubleWidth in class Square: class Square extends Rectangle { public Square(int x, int y, int side) { super(x,y,side,side); } public void doubleWidth() {} // does nothing } > 8. Consider classes representing the following. For each group, show likely > inheritance relationships. Arrows representing inheritance are drawn starting > at the derived class and pointing to the base class: > > (a). Boat, Airplane, Vehicle, Truck, Car, LandVehicle LandVehicle extends Vehicle Airplane extends Vehicle Boat extends Vehicle Car extends LandVehicle Truck extends LandVehicle > (b). Student, Undergrad, GradStudent, Applicant, Person Applicant extends Person Student extends Person Undergrad extends Student GradStudent extends Student > (c) Bird, FlyingBird, Penguin, Hawk, Sparrow FlyingBird extends Bird Penguin extends Bird Hawk extends FlyingBird Sparrow extends FlyingBird