/* +--------------------------+ | interface ISame | +--------------------------+ | boolean same(Object obj) | +--------------------------+ / \ | - - - - - - - - - - - | | +--------------+ +-------------+ | Book | | Author | +--------------+ +-------------+ | String title | | String name | | int year | | int year | +--------------+ +-------------+ +-----------+ | 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); } class Book implements ISame{ String title; int year; Book(String title, int year){ this.title = title; this.year = year; } boolean same(Object obj){ if (obj instanceof Book) return this.same((Book)obj); else return false; /* alternately: throw new ClasCastException( "Cannot compare a Book with other object"); */ } boolean same(Book that){ return this.title.equals(that.title) && this.year == that.year; } } class Author implements ISame{ String name; int year; Author(String name, int year){ this.name = name; this.year = year; } boolean same(Object obj){ if (obj instanceof Author) return this.same((Author)obj); else return false; /* alternately: throw new ClasCastException( "Cannot compare an Author with other object"); */ } boolean same(Author that){ return this.name.equals(that.name) && this.year == that.year; } } // functional iterator for a linear traversal of a data structure interface Traversal{ // is there a current element available in the structure boolean hasMore(); // produce the current element of the structure Object current(); // produce an iterator for the rest of this structure Traversal advance(); } interface ILoObject extends Traversal{ // is there a current element available in the structure boolean hasMore(); // produce the current element of the structure Object current(); // produce an iterator for the rest of this structure Traversal advance(); // to compute the size of this list int size(); // is the given book in this list? boolean contains (Object that); } class MTLoObject implements ILoObject{ MTLoObject() {} // is there a current element available in the structure boolean hasMore(){ return false; } // produce the current element of the structure Object current(){ return "Error"; } // throw new NoSuchElementException("Cannot produce current element in an empty list"); } // produce an iterator for the rest of this structure Traversal advance(){ return this; } // throw new NoSuchElementException("Error - cannot advance in an empty list"); } int size(){ return 0; } boolean contains (Object that){ return false; } } class ConsLoObject implements ILoObject{ Object first; ILoObject rest; ConsLoObject(Object first, ILoObject rest){ this.first = first; this.rest = rest; } // is there a current element available in the structure boolean hasMore(){ return true; } // produce the current element of the structure Object current(){ return this.first; } // produce an iterator for the rest of this structure Traversal advance(){ return this.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); } } class Examples{ Examples () {} Book b1 = new Book("DVC", 2003); Book b2 = new Book("LPP", 1942); Book b3 = new Book("HtDP", 2001); ILoObject mtbooks = new MTLoObject(); ILoObject booklist = new ConsLoObject(b1, new ConsLoObject(b2, mtbooks)); boolean testSizeBook1 = mtbooks.size() == 0; boolean testSizeBook2 = booklist.size() == 2; boolean testContainsBook1 = this.mtbooks.contains(this.b1) == false; boolean testContainsBook2 = this.booklist.contains(this.b2) == true; boolean testContainsBook3 = this.booklist.contains(b3) == false; Author a1 = new Author("DB", 1956); Author a2 = new Author("StEx", 1900); Author a3 = new Author("MF", 1972); ILoObject mtauthors = new MTLoObject(); ILoObject authorlist = new ConsLoObject(a1, new ConsLoObject(a2, mtauthors)); boolean testSizeAuthor1 = mtauthors.size() == 0; boolean testSizeAuthor2 = authorlist.size() == 2; boolean testContainsAuthor1 = this.mtauthors.contains(this.a1) == false; boolean testContainsAuthor2 = this.authorlist.contains(this.a2) == true; boolean testContainsAuthor3 = this.authorlist.contains(a3) == false; // compute the size of the data set given by the traversal int size(Traversal t){ if (t.hasMore()) return 1 + size(t.advance()); else return 0; } // does the data set given by the traversal contain the given book? boolean containsBook(Book b, Traversal t){ if (t.hasMore()) return ((Book)t.current()).same(b) || containsBook(b, t.advance()); else return false; } // does the data set given by the traversal contain the given object? boolean contains(Object obj, Traversal t){ if (t.hasMore()) return ((ISame)t.current()).same(obj) || contains(obj, t.advance()); else return false; } boolean testSizeBookT1 = this.size(this.mtbooks) == 0; boolean testSizeBookT2 = this.size(this.booklist) == 2; boolean testContainsBookT1 = this.containsBook(this.b1, this.mtbooks) == false; boolean testContainsBookT2 = this.containsBook(this.b2, this.booklist) == true; boolean testContainsBookT3 = this.containsBook(b3, this.booklist) == false; boolean testContainsT1 = this.contains(this.b1, this.mtbooks) == false; boolean testContainsT2 = this.contains(this.b2, this.booklist) == true; boolean testContainsT3 = this.contains(b3, this.booklist) == false; boolean testSizeAuthorT1 = this.size(this.mtauthors) == 0; boolean testSizeAuthorT2 = this.size(this.authorlist) == 2; }