CSC 207 Grinnell College Fall, 2014
 
Algorithms and Object-Oriented Design
 

Laboratory: Generics and Interfaces

Summary

In this lab, you will explore both interfaces and Java generics by writing a generic interface and creating classes that implement it.

Introduction

In this lab, you'll be creating an interface that allows one to extract individual components from some linearly indexed object. This is exactly analagous to the behavior of arrays. However, not all objects are naturally stored as arrays. While we may want to provide that kind of access, it may not be expedient to store them linearly.

Thus, you will create an interface that indicates this kind of access and create some implementations that provide it on top of some type that are not necessarily stored in a linearly indexed fashion. In particular, this lab develops the following hierarchy:

class hierarchy for Indexable

In summary,

Creating the Interface Indexable

To get started, it will be useful to create a new project within Eclipse and define the Interface Indexable

  1. Create a project indexableExample within Eclipse.

  2. Create an interface called Indexable that is parameterized by a single type, let's call it ComponentType.

  3. Within Indexable, define two methods:

An IndexableString Class

Strings are fairly naturally linearly indexed, since that is essentially how they are stored in memory (though Java shields us from this, unlike C).

  1. Implement a simple type of indexable object, based on an underlying string. That is, an IndexableString will implement the Indexable interface by working with the individual characters in a string.

    1. Create a class called IndexableString that implements the Indexable interface. What should the parameterized type be (i.e., what type should be returned by get for a string)?
    2. Add empty stubs for the methods required by the interface, but do not implement them yet (i.e., you can return 0 or null)
    3. Check to see that your new class compiles. If you need help, be sure to talk with a neighbor or the instructor.
    4. Why might it be convenient if we could say "IndexableString IS-A String"?
    5. Create your class so that this is true (i.e., create a subclass relationship using extends).
    6. Now re-compile your code. What happens? Why?
    7. It turns out that Java prevents us from creating an IS-A relationship, so the best we can do is to use a HAS-A relationship. Add a member and constructor so that IndexableString does indeed have a String field to work with in its two required functions.
    8. Now, go ahead and implement the two functions required by the interface. If you explore the String object methods in the API, it shouldn't be very hard!

An IndexableInteger Class

Typically, the individual (base 10) digits of integers are not usually indexed, so it might be useful to provide a class for this in some applications.

Let's say that our convention will be that indexing starts with the right-most digit (the "ones place"), and is zero based. Thus, get(2) on an IndexableInteger should return the digit in the "hundreds" place, or the third digit from the right.

How should we handle the indexing of negative numbers? For simplicity, we'll specify that the length only includes the number of digits, and that indexing always returns positive numbers.

  1. Create a class called IndexableInteger that implements the Indexable interface.
    1. What should the parameterized type be (i.e., what type should be returned by get for an integer)?
    2. Once again, we would really like the IS-A relation to be true, but Integer suffers from the same issue as String. Use similar techniques for a HAS-A relationship. Note that you may want to use the primitive type, rather than the Integer class wrapper to simplify your two method implementations.
    3. Create empty stub methods for the interface methods as before.
    4. How can we implement length? Algorithmically, speaking, this is the number of times we can divide the number by 10 before we get a number whose absolute value is less than 10. Use this technique to implement the method.
    5. Write a small test program to see if your length function works correctly (you could just add a static main to the IndexableInteger class). Be sure to test on negative numbers and numbers that are between -10 and 10.
    6. The implementation of get mathematically straightforward, but there are a few special cases to watch out for.
      • If the index equals or exceeds the length, that's "exceptional" (i.e., a problem).
      • If the index is 0, you can find the last digit by returning the number modulo 10.
      • Otherwise, you can "shift" off the rightmost digits by dividing by 10index (using integer division). The digit is the quotient modulo 10.

        Hint: You may want to define a method powerOf10 (int n) that raises 10 to a specified poser, where n is an integer. (Do NOT use the java.lang.Math library, because the general pow method uses power series which are computationally expensive for integral powers.)

      • You'll need to watch out for and handle negative numbers correctly.
    7. Test your implementation on several numbers.

The TextIndexable Class

Now that you've had some practice with declaring interfaces and implementing some classes that make use of generics (even though these implementations are not generic at all!), now you can do some very generic things. (But don't tell your parents that you came to college to do generic things in class.)

  1. Create a "driver" class called TestIndexable.
    1. In the main method of your class, create an ArrayList of Indexable objects.
    2. Add several indexable string and integer objects to the ArrayList.
    3. Use Java's "enhanced" for loop to print the component at the second index of every item in the list.

This document is available on the World Wide Web as


http://www.walker.cs.grinnell.edu/courses/207.sp012/labs/lab-generics.shtml

created 15 January 2009 by Jerod Weinman
revised 10 February 2011 by Jerod Weinman
revised 13 February 2012 by Henry M. Walker
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu.