import tester.Tester; // to represent a list of books abstract class ALoB { // is there a book written by "MF" in this list? abstract boolean anyBookWrittenByMF(); // is there a book published before 1980 in this list? abstract boolean anyBookBefore1980(); // is there a book that costs more than $10 in this list? abstract boolean anyBookMoreThan10(); // is there a book that satisfies the condition? abstract boolean hasProperty(ISelectBook choose); } // to represent an empty list of books class MTLoB extends ALoB { MTLoB() { } boolean anyBookWrittenByMF(){ return false; } boolean anyBookBefore1980(){ return false; } boolean anyBookMoreThan10(){ return false; } boolean hasProperty(ISelectBook choose){ return false; } } // to represent a nonempty list of books class ConsLoB extends ALoB { Book first; ALoB rest; ConsLoB(Book first, ALoB rest) { this.first = first; this.rest = rest; } /* TEMPLATE Fields: ... this.first ... -- Book ... this.rest ... -- ALoB Methods: ... this.first.anyBookWrittenByMF() ... -- boolean ... this.first.anyBookBfore1980() ... -- boolean ... this.first.anyBookMOreThan10() ... -- boolean ... this.first.hasProperty(ISelectBook) ... -- boolean Methods for fields: ... this.first.writtenByMF() ... -- boolean ... this.first.before1980() ... -- boolean ... this.first.moreThan10() ... -- boolean ... this.rest.anyBookWrittenByMF() ... -- boolean ... this.rest.anyBookBfore1980() ... -- boolean ... this.rest.anyBookMOreThan10() ... -- boolean ... this.rest.hasProperty(ISelectBook) ... -- boolean */ boolean anyBookWrittenByMF(){ return this.first.writtenByMF() || this.rest.anyBookWrittenByMF(); } boolean anyBookBefore1980(){ return this.first.before1980() || this.rest.anyBookBefore1980(); } boolean anyBookMoreThan10(){ return this.first.moreThan10() || this.rest.anyBookMoreThan10(); } boolean hasProperty(ISelectBook choose){ return choose.selectBook(this.first) || this.rest.hasProperty(choose); } } // to represent a book class Book { String author; int year; int price; Book(String author, int year, int price) { this.author = author; this.year = year; this.price = price; } /* TEMPLATE Fields: ... this.author ... -- String ... this.year ... -- int ... this.price ... -- int Methods: ... this.anyBookWrittenByMF() ... -- boolean ... this.anyBookBfore1980() ... -- boolean ... this.anyBookMOreThan10() ... -- boolean ... this.hasProperty(ISelectBook) ... -- boolean */ // is this book written by "MF" boolean writtenByMF(){ return this.author.equals("MF"); } // was this book published before 1980 boolean before1980(){ return this.year < 1980; } // does this book cost more than $10 boolean moreThan10(){ return this.price > 10; } } // to represent a predicate for books interface ISelectBook{ // determine whether the given book satisfies a condition public boolean selectBook(Book b); } // book predicate: selects books written by MF class WrittenByMF implements ISelectBook{ // was the given book written by "MF" public boolean selectBook(Book b){ return b.author.equals("MF"); } } //book predicate: selects books written before 1980 class Before1980 implements ISelectBook{ // was the given book published before 1980 public boolean selectBook(Book b){ return b.year < 1980; } } //book predicate: selects books that cost morre than $10 class MoreThan10 implements ISelectBook{ // does the given book cost more than $10 public boolean selectBook(Book b){ return b.price > 10; } } //book predicate: selects books written by the given author class WrittenBy implements ISelectBook{ String author; WrittenBy(String author){ this.author = author; } // was the given book written by this author? public boolean selectBook(Book b){ return b.author.equals(this.author); } } /* + - - - - - - - - - - - + | | v | +----------------------------+ | I: ISelectBook | | +----------------------------+ | boolean selectBook(Book b) | | +----------------------------+ | + - - - - - - - - + - - - - - - - + - - - + - - - - + | | | | | | | | +-------------+ +------------+ +------------+ +---------------+ | WrittenByMF | | Before1980 | | MoreThan10 | | WrittenBy | +-------------+ +------------+ +------------+ +---------------+ +-------------+ +------------+ +------------+ | String author | +---------------+ */ class Examples{ Examples(){} Book b1 = new Book("MF", 2001, 60); Book b2 = new Book("EX", 1942, 15); Book b3 = new Book("JL", 1900, 8); Book b4 = new Book("MF", 1998, 15); ALoB mtlist = new MTLoB(); ALoB list1 = new ConsLoB(b1, new ConsLoB(b4, mtlist)); ALoB list2 = new ConsLoB(b3, mtlist); ALoB list3 = new ConsLoB(b2, new ConsLoB(b3, mtlist)); ALoB list4 = new ConsLoB(b1, new ConsLoB(b4, new ConsLoB(b3, mtlist))); ALoB list5 = new ConsLoB(b2, new ConsLoB(b3, list1)); // tests for predicates in the class Book boolean testWrittenByMF(Tester t) { return t.checkExpect(this.b1.writtenByMF(), true) && t.checkExpect(this.b2.writtenByMF(), false); } boolean testBefore1980(Tester t) { return t.checkExpect(this.b1.before1980(), false) && t.checkExpect(this.b2.before1980(), true); } boolean testMoreThan10(Tester t) { return t.checkExpect(this.b1.moreThan10(), true) && t.checkExpect(this.b3.moreThan10(), false); } // tests for the method anyBookWrittenByMF boolean testAnyBookWrittenByMF(Tester t) { return t.checkExpect(this.mtlist.anyBookWrittenByMF(), false) && t.checkExpect(this.list1.anyBookWrittenByMF(), true) && t.checkExpect(this.list2.anyBookWrittenByMF(), false); } // tests for the method anyBookBefore1980 boolean testAnyBookBefore1980(Tester t) { return t.checkExpect(this.mtlist.anyBookBefore1980(), false) && t.checkExpect(this.list5.anyBookBefore1980(), true) && t.checkExpect(this.list1.anyBookBefore1980(), false); } // tests for the method anyBookMoreThan10 boolean testAnyBookMoreThan10(Tester t) { return t.checkExpect(this.mtlist.anyBookMoreThan10(), false) && t.checkExpect(this.list1.anyBookMoreThan10(), true) && t.checkExpect(this.list2.anyBookMoreThan10(), false); } // tests for the method anyBookWrittenByMF boolean testAnyBookWrittenByMFa(Tester t) { return t.checkExpect(this.mtlist.hasProperty(new WrittenByMF()), false) && t.checkExpect(this.list1.hasProperty(new WrittenByMF()), true) && t.checkExpect(this.list2.hasProperty(new WrittenByMF()), false); } // tests for the method anyBookBefore1980 boolean testAnyBookBefore1980a(Tester t) { return t.checkExpect(this.mtlist.hasProperty(new Before1980()), false) && t.checkExpect(this.list5.hasProperty(new Before1980()), true) && t.checkExpect(this.list1.hasProperty(new Before1980()), false); } // tests for the method anyBookMoreThan10 boolean testAnyBookMoreThan10a(Tester t) { return t.checkExpect(this.mtlist.hasProperty(new MoreThan10()), false) && t.checkExpect(this.list1.hasProperty(new MoreThan10()), true) && t.checkExpect(this.list2.hasProperty(new MoreThan10()), false); } // tests for the method anyBookWrittenBy boolean testAnyBookWrittenByX(Tester t) { return t.checkExpect(mtlist.hasProperty(new WrittenBy("MF")), false) && t.checkExpect(this.list1.hasProperty(new WrittenBy("MF")), true) && t.checkExpect(this.list2.hasProperty(new WrittenBy("MF")), false); } /* A1: true for list1, false for list2, false for mtlist B1: true for list1, false for list5, true for mtlist C1: from list 5 produces list 1 A2: true for list5, false for list1, false for mtlist B2: true for list3, false for list5, true for mtlist C2: from list4 produces list3 A3: true for list1, false for list2, false for mtlist B3: true for list3, false for list4, true for mtlist C3: for list4 produces list1 */ }