import tester.*; // to represent a book and its author class Book{ String title; Author author; // Constructor for a book that // notifies the author that his book has been published Book(String title, Author author){ this.title = title; this.author = author; this.author.addBook(this); } /* TEMPLATE ... this.title ... -- String ... this.author ... -- Author METHODS: ... this.sameBook(Book) ... -- boolean METHODS FOR FIELDS: ... this.author.addBook(Book) ,,, -- void ... this.author.sameAuthor(Author) ... -- boolean */ // is this book the same as the given book? boolean sameBook(Book that){ return this.title.equals(that.title) && // here we only check the author's name to break the circularity this.author.name.equals(that.author.name); } } // to represent an author of a book class Author{ String name; Book book; // Constructor for the author who has yet to write a book Author(String name){ this.name = name; } /* TEMPLATE ... this.name ... -- String ... this.book ... -- Book METHODS: ... this.sameAuthor(Author) ... -- boolean METHODS FOR FIELDS: ... this.book.sameBook(Book) ... -- boolean */ // EFFECT: // make the given book this author's book void addBook(Book book){ this.book = book; } // is this author the same as the given author? boolean sameAuthor(Author that){ return this.name.equals(that.name) && this.book.sameBook(that.book); } } // Examples for circularly referential books and authors class ExamplesBook{ ExamplesBook(){} // three authors Author mf = new Author("MF"); Author mf2 = new Author("MF"); Author ebw = new Author2("EBW"); // and the three book they wrote Book htdp = new Book("HtDP", this.mf); Book htdp2 = new Book("HtDP", this.mf2); Book eos = new Book("EOS", this.ebw); // test the method sameBook and some properties of the Book/Author data void testSameBook(Tester t){ t.checkExpect(this.htdp.author.name, "MF"); t.checkExpect(this.htdp.title, "HtDP"); t.checkExpect(this.eos.author.name, "EBW"); t.checkExpect(this.htdp.sameBook(this.htdp2), true); } }