interface IFilter{ // method that selects objects with some property boolean select(); } interface IFilter2{ // method that selects objects with some property boolean select2(Object obj); } class CheapBook implements IFilter2{ // determine whether the given book is cheap boolean select2(Object obj){ return ((Book)obj).price < 10; } } class NewAuthor implements IFilter2{ // determine whether the given book was written by contemporary author boolean select2(Object obj){ return ( ((Book)obj).author.isContemporary() ); } } class Book implements IFilter{ String title; Author author; int price; Book(String title, Author author, int price) { this.title = title; this.author = author; this.price = price; } boolean equals(Object obj){ return (this.title.equals( ((Book) obj).title)) && (this.author.equals( ((Book) obj).author)) && (this.price == ((Book) obj).price); } boolean select(){ return this.price < 10; } } class Author implements IFilter{ String name; int year; Author(String name, int year){ this.name = name; this.year = year; } boolean equals(Object obj) { return (this.name.equals( ((Author) obj).name )) && (this.year == ( ((Author) obj).year )); } boolean select(){ return this.year > 1940; } // determine whetheri this is a contemporary author boolean isContemporary(){ return this.year > 1940; } } abstract class ALoObj{ // count the number of items in this list abstract int count(); // determine whether this list contains the given object abstract boolean contains(Object obj); // remove the first occurrence of the given object from this list abstract ALoObj remove(Object obj); // determine whether there is a 'selected' object in this list abstract boolean orMap(); // determine whether there is a 'selected' object in this list abstract boolean orMap2(IFilter2 filter); } class MTLoObj extends ALoObj{ MTLoObj(){ } int count(){ return 0; } boolean contains(Object obj){ return false; } ALoObj remove(Object obj){ return this; } boolean orMap(){ return false; } boolean orMap2(IFilter2 filter){ return false; } } class ConsLoObj extends ALoObj{ Object fst; ALoObj rst; ConsLoObj(Object fst, ALoObj rst){ this.fst = fst; this.rst = rst; } // Template: // ...this.fst... // ...this.rst... // ...this.count()... // ...this.contains(Object obj)... // ...this.remove(Object obj)... // ...this.rst.orMap()... int count() { return 1 + this.rst.count(); } boolean contains(Object obj){ return (this.fst.equals(obj)) || (this.rst.contains(obj)); } ALoObj remove(Object obj){ if (this.fst.equals(obj)) return this.rst; else return new ConsLoObj(this.fst, this.rst.remove(obj)); } boolean orMap(){ return ( ((IFilter)(this.fst)).select() ) || (this.rst.orMap()); } boolean orMap2(IFilter2 filter){ return filter.select2(this.fst) || (this.rst.orMap2(filter)); } } // "Examples" // // Author mf = new Author("Matthias", 1958); // // Author bard = new Author("Shakespeare", 1716); // // Book b1 = new Book ("HtDP", mf, 60); // // Book b2 = new Book ("LL", mf, 18); // // Book b3 = new Book ("Hamlet", bard, 7); // // ALoObj mtlist = new MTLoObj(); // // ALoObj list1 = new ConsLoObj(b1, new ConsLoObj(b2, mtlist)); // // ALoObj list2 = new ConsLoObj(b3, list1); // // // "Testing the count() method in class ListofObj" // // mtlist.count() == 0 // // list1.count() == 2 // // list2.count() == 3 // // "Testing the contains() method in class ListofObj" // // mtlist.contains(b1) == false // // list1.contains(b3) == false // // list2.contains(b3) == true // // list2.contains(b2) == true // // "Testing the remove() method in class ListofObj" // // mtlist.remove(b1).equals(mtlist) // // list1.remove(b3).count() // // list2.remove(b3).count() // // "Testing select() method in class Book" // // b1.select() == false // // b2.select() == true // // "Testing select() method in class Author" // // mf.select() == true // // bard.select() == false // // "Testing orMap() method on lists of books" // // mtlist.orMap() == false // // list1.orMap() == false // // list2.orMap() == true // // CheapBook cheapFilter = new CheapBook(); // // mtlist.orMap2(cheapFilter) == false // // list1.orMap2(cheapFilter) == false // // list2.orMap2(cheapFilter) == true // // NewAuthor authorFilter = new NewAuthor(); // // mtlist.orMap2(authorFilter) == false // // list1.orMap2(authorFilter) == true // // list2.orMap2(authorFilter) == true // // Examples // // Author mf = new Author("Matthias" 1958); // Author bard = new Author("Shakespeare", 1716); // // Book b1 = new Book ("HtDP", mf, 2001); // Book b2 = new Book ("LL", mf, 1974); // Book b3 = new Book ("Hamlet", bard, 1736); // // ALoObj mtlist = new MTLoObj(); // ALoObj list1 = new ConsLoObj(b1, new ConsLoObj(b2, mtlist)); // ALoObj list2 = new ConsLoObj(b3, mtlist); // // "Testing the count() method in class ListofObj" // mtlist.count() == 0; // list1.count() == 2; // list2.count() == 3; // // "Testing the contains() method in class ListofObj" // mtlist.contains(b1) == false; // list1.contains(b3) == false; // list2.contains(b3) == true // list2.contains(b2) == true; // // "Testing the remove() method in class ListofObj" // mtlist.remove(b1).equals(mtlist); // list1.remove(bard).equals(list1); // list2.remove(b3).equals(list1); // // NewAuthor authorFilter = new NewAuthor(); // mtlist.orMap2(authorFilter) == false // list1.orMap2(authorFilter) == true // list2.orMap2(authorFilter) == true //