SWE 619 In Class Exercise Number 13


How well are you prepared for the final? This exercise should help you find out. Piazza discussions encouraged!
// Chooser - a class badly in need of generics!
// Bloch 3rd edition, Chapter 5, Item 28:  Prefer lists to arrays

public class Chooser<E> {
   // Overview:  A Chooser is a non-empty bag of "E"s
   // rep-invariant?

   // would a map be a better representation?
   private final List<E> choiceList;

   public Chooser (List<E> choiceList) {
      this.choiceList = choiceList;
   }

   // return a random E from this
   public E choose() { 
      Random rnd = ThreadLocalRandom.current();
      return choiceList.get(rnd.nextInt(choiceList.size()));
   }

   // A mutator to add a choice
   public void addChoice( E choice) {...}

   // standard recipe or no?
   @Override public boolean equals (Object obj) {...}

   // standard recipe or no?
   @Override public int hashCode () {...}

   // what is appropriate here?
   @Override public String toString () {...}
}
  1. The (client-visible) overview constrains the implementation. How does it do that, and how should the rep-invariant capture that constraint?

  2. The constructor's implementation fails Liskov's correctness test. Explain, then fix it.

  3. Write a reasonable contract for the constructor.

  4. Bloch wouldn't like the method header for the constructor. Why not? Fix it.

  5. Besides the correctness problem, the constructor's implementation has another problem that Bloch would object to. What is it? Fix it.

  6. Given the overview, what should be the output of a reasonable toString() method? Show some examples.

  7. Is Bloch's standard recipe for equals() appropriate here? If not, give a test case that shows the problem. Do the same for hashCode().

  8. Specify and implement addChoice().

  9. Suppose we want the Chooser class to be immutable. What has to change?

  10. Suppose we decide to disallow null values in the Chooser. Is this client visible? Should this change the rep-invariant? What changes?