/* +-----------+ | ILoObject |<------------+ +-----------+ | +-----------+ | / \ | --- | | | ------------------- | | | | +------------+ +----------------+ | | MTLoObject | | ConsLoObject | | +------------+ +----------------+ | +------------+ +-| Object first | | | | ILoObject rest |-+ | +----------------+ | | +--------------------------+ | | interface ISame | | +--------------------------+ | | boolean same(Object obj) | | +--------------------------+ | / \ | | | - - - - - - v | +------------+ | Object | +------------+ | Type ??? | | ... | +------------+ */ interface ISame{ // is this the same as the given object? boolean same(Object obj); } interface Traversal{ // are there any elements in this data set? boolean hasMore(); // produce the current first element in this data set Object current(); // produce a traversal for the remainder of this data set Traversal advance(); } interface ISelect{ // does the given object have the desired property? boolean choose(Object obj); } class Book{ String title; String author; Book(String title, String author){ this.title = title; this.author = author; } } // selector for books written by Shakespeare class ByShakespeare implements ISelect{ // is the given book written by Shakespeare? boolean choose(Object obj){ return ((Book)obj).author.equals("Shakespeare"); } } // selector for books with the given title class ByTitle implements ISelect{ String title; ByTitle(String title){ this.title = title; } // does the given book have this title boolean choose(Object obj){ return ((Book)obj).title.equals(this.title); } } interface ILoObject extends ISame, Traversal{ // to compute the size of this list int size(); // is the given book in this list? boolean contains (Object that); // is this the same as the given object? boolean same(Object obj); } class MTLoObject implements ILoObject{ MTLoObject() {} int size(){ return 0; } boolean contains (Object that){ return false; } // is this the same as the given object? boolean same(Object obj){ return obj instanceof MTLoObject; } // are there any elements in this data set? boolean hasMore(){ return false; } // produce the current first element in this data set Object current(){ // should throw an IllegalOperationException return new Error("no current in en empty data set"); } // produce a traversal for the remainder of this data set Traversal advance(){ // should throw an IllegalOperationException return this; } } class ConsLoObject implements ILoObject{ Object first; ILoObject rest; ConsLoObject(Object first, ILoObject rest){ this.first = first; this.rest = rest; } /* TEMPLATE: ... this.first ... -- Object ... this.rest ... -- ILoObject ... this.rest.size() ... -- int ... this.rest.contains( Object ) ... -- boolean */ int size(){ return 1 + this.rest.size(); } boolean contains (Object that){ return ((ISame)this.first).same(that) || this.rest.contains(that); } // is this the same as the given object? boolean same(Object obj){ if (obj instanceof ConsLoObject) return this.sameConsLoObject(((ConsLoObject)obj)); else return false; } // is this the same as the given ConsLoObject? boolean sameConsLoObject(ConsLoObject that){ return ((ISame)this.first).same(that.first) && this.rest.same(that.rest); } // are there any elements in this data set? boolean hasMore(){ return true; } // produce the current first element in this data set Object current(){ return this.first; } // produce a traversal for the remainder of this data set Traversal advance(){ return this.rest; } } class Error{ String message; Error(String message){ this.message = message; } } class Examples{ Examples () {} Book b1 = new Book("Tortilla Flat", "Steinbeck"); Book b2 = new Book("Pearl", "Steinbeck"); Book b3 = new Book("Othello", "Shakespeare"); ILoObject mt = new MTLoObject(); ILoObject shorty = new ConsLoObject(this.b1, new ConsLoObject(this.b2, this.mt)); ILoObject list = new ConsLoObject(this.b3, this.shorty); ByShakespeare byS = new ByShakespeare(); // does the collection of data generated by the given traversal // contain an object specified by the given ISelect selector? boolean contains(Traversal tr, ISelect select){ if (tr.hasMore()){ // non-empty clause if (select.choose(tr.current())) return true; else return this.contains(tr.advance(), select); } else // empty clause return false; } /* TEMPLATE: ... tr.hasMore() ... -- boolean if == false - nothing more available if == true: ... tr.current() ... -- Object ... tr.advance() ... -- Traversal ... select.choose(Object) ... -- boolean ... contains(Traversal, select) ... -- boolean */ // tests for the method contains: boolean testContains1 = this.contains(mt, byS) == false; boolean testContains2 = this.contains(shorty, byS) == false; boolean testContains3 = this.contains(list, byS) == true; boolean testContains4 = this.contains(mt, new ByTitle("Pearl")) == false; boolean testContains5 = this.contains(shorty, new ByTitle("Othello")) == false; boolean testContains6 = this.contains(list, new ByTitle("Othello")) == true; }