/* +--------------------------+ | 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; } } interface ILoObject{ // 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() {} 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; } /* 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; }