Design recipes for methods for unions of classes. Design recipes for method for classes that represent self-referential data. Abstracting common data and common behavior in unions of classes.
The only data we need is the list of books.
// PURPOSE AND CONTRACT: // count the number of books in this list abstract int count();
We develop the methods in the two classes concurrently, starting with examples.
Book b1 = new Book("HtDP", "Matthias", 60, 2001); Book b2 = new Book("Beach Music", "Conroy", 20, 1996); Book b3 = new Book("3 Com", "Remarque", 15, 1937); ALoB mtlob = new MtLoB(); ALoB lob1 = new ConsLoB(b1, mtlob); ALoB lob2 = new ConsLoB(b2, lob1); ALoB lob3 = new ConsLoB(b3, lob2); ... mtlob.count() -- expected: 0 lob1.count() -- expected: 1 lob2.count() -- expected: 2 lob3.count() -- expected: 3
There is a separate template for each of the two subclasses.
/* TEMPLATE for the MtLoB class: int count() { ... } */ /* TEMPLATE for the ConsLoB class: int count() { ... this.fst ... ... this.rst.count() ... } */
Again, we have two different methods, one for each class.
// PROGRAM for the class MtLoB: int count() { return 0; } // PROGRAM for the class ConsLoB: int count() { return 1 + this.rst.count(); }
mtlob.count() == 0 lob1.count() == 1 lob2.count() == 2 lob3.count() == 3