CS 261 Lab #3

January 31st

Goals:

This week you'll get some hands-on practice with interfaces and polymorphism. I'm suggesting again that you use BlueJ for this lab.

Partners

In each lab this semester you will work with a randomly assigned partner. (I'll have Zoom randomly set up breakout rooms.) Please be kind in your interactions with your partners! Keep in mind that students in this class have a range of previous programming experience, and that some have been college students for longer than others. We're all in this together, and you have something to learn from your partner, no matter who they are or what their previous experiences have been. I expect that group members will collaborate and work together on each step of the lab.

Exercise 1: Create and use an Interface

  1. Take a moment to introduce yourself to your partner(s). After social pleasantries are complete, pick one member of the team to be the "typer". They'll share their screen while editing the lab code in BlueJ. (I think BlueJ works better for these interactions than Eclipse. It's easier to see when sharing screens, and makes it easier to quickly test individual methods than Eclipse does.) Group members should contribute equally while working through the problems below and discuss all code to be written, though only the "typer" will be able to edit code. Resist the temptation to have both members work simultaneously in BlueJ — you're much more likely to "drift apart" over the course of the lab if you do so. The goal here is to have a partner who's engaged on exactly the same step of the lab as you are.

    Consider letting the less experienced member of the group do the typing if it seems like there's a mismatch in experience or comfort levels. That will help make sure they don't get left behind. Worst case, flip a coin to see who does the typing. Or have Java generate a random boolean value. (Type (new java.util.Random()).nextBoolean() in the codepad.)

    At the conclusion of the lab, make arrangements for the typer to share a copy of the code with the other member(s) of the group. (E.g. email it, or put it on a shared Google drive, etc.) My solutions to the lab will get posted as well.

  2. Download the InterfaceLab project and extract its contents (it's a .zip archive), then start BlueJ and open the project.
  3. Take a moment to familiarize yourself with the four classes in the project. There's a Controller, two different classes that can or will be controlled by it (AdventureGame and MarsRover), and a Tester with a main method that starts a round of the adventure game. Run the Tester's main method and play around with the game:

  4. Take a look at the AdventureGame code to get a feel for the methods it contains and how it works. The graphical "remote" has five buttons on it, and each of those buttons causes one of AdventureGame's methods to be called. Can you figure out which five methods in AdventureGame those are?
  5. Take a look inside Controller. You don't need to understand the code that creates the GUI or handles the buttons as they're pressed, but make an effort to see how the code has been tailored to interact with an AdventureGame instance. (Search for "AdventureGame", for example, to see where the class is referred to in the Controller code.)
  6. Change the Controller class so that instead of working with AdventureGame, it works with the MarsRover class instead. Edit Tester and verify that the controller really does control the rover. (Uncomment the last two lines in main, and comment out the line that created the original controller.) Note: An annoying delay has been introduced here when controlling the rover — in real life it takes between 4 and 20 minutes to get a signal to mars!
  7. Now change Controller so that it can work with either an AdventureGame or MarsRover instance. That will require making it polymorphic: the constructor should be able to take either kind of object and control it. Since the game and the rover aren't very similar classes, we'll use an interface to pull this off:

Exercise 2: Mixing in Subclasses

  1. Create a subclass of AdventureGame called TrickyGame that cheats somehow. (For example, change the location of the flashlight every once in a while, or lie when giving hints.) Don't have it implement the interface — just extend AdventureGame.
  2. Update the Tester class and see if you can control a TrickyGame with the polymorphic Controller. Should it work? Does it?
  3. Can TrickyGame both extend AdventureGame and implement your interface? Does that change the results of the last experiment?

Exercise 3: Even more Interfaces

  1. In class, we looked at the Comparable interface. Modify AdventureGame so that it implements Comparable<AdventureGame> — that is, add a compareTo method that determines whether a given game instance is less than, equal to, or greater than another game instance. (You could base that decision off of the distance between the player's current position and the flashlight, for example, or the player's location — you decide.)
  2. Once you've implemented the Comparable interface, see if you can sort a collection of game instances. See this code for an example of how I sorted a group of Radios in class.

Extras

If you've got extra time and are bored, consider trying the following:
  1. Dream up an additional class that implements your interface, and demonstrate that it can be used with the GUI.
  2. Write additional polymorphic methods that take advantage of the interface you defined. Can you take an ArrayList of game-like objects, and call up() on each of them, for example?
  3. How would you broaden your compareTo method in AdventureGame so that a caller could ask you to compare an AdventureGame instance to any other kind of object?
  4. Ponder: Instead of an interface, could we have used an abstract class instead (with AdventureGame and MarsRover being subclasses)? Which methods would be abstract and which would be concrete (fully defined)? Which approach seems best (interface or abstract class)?
  5. Read up on Exceptions. Have MarsRover throw an exception if the rover goes off the edge of the "world".


Brad Richards, 2023