CS 302 Lab 14

Lab 14: Interfaces and Comparing: Playing Cards

CS302, UW-Madison

Task 1: Evaluations

Please check your email and complete course evaluations as well as an online survey in Learn@UW:

The course survey is at the CS302 Learn@UW website. Once there, choose "Surveys" from the menu on the upper-left of the page. Then choose the "CS302-Survey" and complete it as instructed. When finished, make sure to click on the "Submit" button at the bottom-right at the end of the survey to receive credit for this lab.

Today We'll be:

Overview

In Java, an interface is used as a way of ensuring that a group of classes behave in a similar way without requiring those classes to be related through inheritance (i.e., through a class hierarchy). A common behavior, that we'll be exploring below, is to make a class comparable so that instances of the class can be compared to determine their ordering. We'll first see how the Comparable interface works with the String class and then we'll implement this interface for our own class.

Getting Started

Begin by starting a new project in Eclipse. Name your project InterfaceLab and create a main class named InterfaceMain. Then download the following files to your InterfaceLab folder ("src" folder if you've made one for your project).

Task 2: Strings and the Comparable Interface

We've learned that we can compare two strings to see if they are equal using the equals method as in this example:

    String s1 = "Tim";
    String s2 = "Jim";
    if (s1.equals(s2)) { System.out.println("the strings are equal"); }

What would we do if we wanted to determine which string comes first alphabetically? Though you might try s1 < s2, it would only compare the addresses in the two reference variables (like s1 == s2 only compares addresses). To compare objects in Java we use the Comparable interface. Classes that implement this interface must have a compareTo method that is used to compare two objects to see if one is less than, equal to, or greater than the other. For two strings variables s1 and s2, s1.compareTo(s2) returns an integer value that is:

Let's give this a try. In your main class, write a small program that reads two strings and then displays the string that comes first alphabetically, but if the two strings are equal, then your program displays, "The two strings are equal."

Once you've written this program demonstrate it for your Lab TA.

For the program above, we used the compareTo method directly, but it is also used indirectly in other methods that solve common problems as we'll see with sorting an array of strings. First, create an array of Comparable objects that contains strings and fill it with a ten names in unsorted order:

    Comparable[] collection = new Comparable[10];
    collection[0] = "Jim";
    collection[1] = "Deb";
    . . .

Now we'll sort the array to put the strings in alphabetical order. Sorting the array is simple if we use Java's sort method, but this sort method requires that the objects are comparable (i.e., have a compareTo method as Strings do). Here's how we call sort in Java:

    Arrays.sort(collection);

Add this to your main class and also import Java.util.Arrays to be able to use sort. Follow the sort method call with a loop that displays the contents of your array. Then run your program to verify that the array is correctly sorted.

Once you've written your program to demonstrate how to successfully sort an array, show your it to your Lab TA.

Task 3: Implementing the Comparable<T> Interface in your own Class

When you define a new class, consider if it makes sense for instances of your class to be compared to do things such as sorting. If so, your class should implement the Comparable<T> interface. To do this you need to:

In general, a class that implements a particular interface must include an implements clause in the class header and implement all of the methods specified by the interface.

Now take a look at the PlayingCard class that you downloaded. This class defines a playing card that would be used in card games. Recall that playing cards have ranks ace, 2, 3, ..., 9, 10, jack, queen, king; and suits spades, clubs, diamonds, and hearts. Playing cards are typically ordered by rank with ace being either highest or lowest. Modify the PlayingCard class so that it implements the Comparable<T> interface that orders cards by their rank with ace being lowest and king being highest.

After you've modified the PlayingCard class, then replace the strings in your array of Comparable objects with playing cards. In Eclipse, this may case the following warning:

Comparable is a raw type. References to generic type Comparable<T> should be parameterized.

Please ignore this compiler warning.  We are demonstrating the ability of the raw type Comparable and thus we do not wish to parameterize this generic type for this lab. However, in most cases, it would be considered good programming practice to parameterize as Comparable<PlayingCard>

Also Note: PlayingCard uses exceptions to indicate when a card is given an invalid rank or suit so you should use a try-catch statement appropriately. Fill the collection array with a variety of different ranks (and suits) in unsorted order. Then sort and display the collection as before. What you should notice is that you can now sort an array of playing cards using the same sort method and the same loop to display the collection. A key benefit of using interfaces is that we can then write a single method to solve a common problem, like sorting, that works for any objects so long as the classes for that type of object implement the interface. With this technique we do not need a method to sort strings, another to sort playing cards, etc. We can simply write one generic method that sorts Comparable objects no matter what they are - strings, playing cards, or some other comparable object. This reduces our effort and code redundancy, and also makes the code more maintainable.

Show your modified PlayingCard class and your main sorting program to your Lab TA before doing the last task.

Task 4: Comparing using Two Values

Playing cards are typically sorted by both their suit and rank. Modify the comparable method of the PlayingCard class so that it sorts first by suit (ordered spades, clubs, diamonds, hearts) and then by rank. Run your program to verify that your method works correctly, and then show this program to your Lab TA.

Challenge Task

Rather than having two exception classes for playing cards, code a single exception class named, InvalidPlayingCardException, that is able to accept a message when the exception is thrown. Make this new exception class an UNchecked exception. Modify the PlayingCard class to use this new exception with a message stating whether the suit or the rank was invalid and also include the invalid value in the message. Also modify your main program to catch and handle your new excecption.

If you finish this challenge, show your new exception class and modified program to your Lab TA before leaving.