/* --- CSU213 Spring 2005 Lecture Notes --------- Copyright 2005 Viera K. Proulx Lecture 6: Help! */ /* Goals: - learn to define and use methods in classes with containment - learn to compare two instances for extensional equality Let us return to defining methods for the class of data that represents books in a library. However, we use the class definition that used a separate class to represent the author, so that several books written by the same author would indeed have the author in common. Here are the classes that represents books and authors: +---------------+ | Book | +---------------+ | String title | | Author author |----+ | int no | | +---------------+ | v +-------------+ | Author | +-------------+ | String name | | int year | +-------------+ */ // to represent a book in a library class Book { String title; Author author; int no; Book(String title, Author author, int no) { this.title = title; this.author = author; this.no = no; } /* // ** DRAFT TEMPLATE ** Edit as needed. ??? mmm() { ... this.title ... ... this.author ... ... this.no ... } */} // to represent the author of a book class Author { String name; int year; Author(String name, int year) { this.name = name; this.year = year; } /* // ** DRAFT TEMPLATE ** Edit as needed. ??? mmm() { ... this.name ... ... this.year ... } */ } /* Before we design any methods, we make a couple of examples of books and authors: Author drs = new Author("Dr Seuss", 1908); Author db = new Author("Dan Brown", 1950); Book ch = new Book("the Cat in a Hat", drs, 66); Book geh = new Book("Green Eggs and Ham", drs, 55); Book dvc = new Book("Da Vinci Code", db, 77); Book cr = new Book("Catcher in a Rye", new Author("JD Salinger", 1940), 42); Let us design a method that will check if this book was written by the author we are thinking of. 1. Problem analysis and data defeinitions: We are now dealing with two classes, and so have to decide not only what data the method consumes and produces, but also in which class should it be defined. In our case, for every book we would like to be able to verify that the author is the one we are thinking of. That indicates, the method should be defined in the class Book. of course, we will need to supply the information about the author as the function argument. Let us first consider the case when we know only the author's name. The method consumes a String and produces a boolean value. 2. Purpose and contract (we will call it 'header'): // determine whether this book was written by author with the given name boolean sameAuthorName(String name){...} 3. Examples: We already know how to write test cases inside of the class Examples. For brevity, we will now write just the method invocation and the expected outcome. ch.sameAuthorName("Dr Seuss) --> true dvc.sameAuthorName("Dr Seuss") --> false cr.sameAuthorName("Dan Brown") --> false 4. Template: The template starts with: ... this.title ... ... this.author ... ... this.price ... We realize, that author is an instance of another class, and so we add to the template: ... this.author.name ... ... this.author.year ... 5. Body At this point we have a choice in how to proceed. The easy way out is to define the body as return this.author.name.equals(name); return this.price - this.price / 5; The complete method is shown below: */ // compute the sale price of this book int salePrice(){ if (this.hardcover) return this.price - this.price / 5; else return this.price; } } /* We copy the examples of data and of the method invocation into the ExamplesBooks class: */ class ExamplesBooks{ ExamplesBooks() {} Book ch = new Book("the Cat in a Hat", "Dr Seuss", 1500, true); Book dvc = new Book("Da Vinci Code", "Dan Brown", 3000, true); Book cr = new Book("Catcher in a Rye", "JD Salinger", 800, false); boolean test1 = this.ch.salePrice() == 1200; boolean test2 = this.dvc.salePrice() == 2400; boolean test3 = this.cr.salePrice() == 800; } /* Next, we want to figure out whether we have enough money to buy a particular book. 1. Problem analysis and data analysis: The method consumes the amount of money we have and produces a boolean value. 2. Purpose and header: // ddetermine whether the given amount is enough to buy this book boolean enoughMoney(int amount) {...} 3. Examples: ch.enoughMoney(2000) == true dvc.enoughMoney(2000) == false 4. Template: --- we can now add the method we already defined --- ... this.title ... ... this.author ... ... this.price ... ... this.salePrice() ... 5. Body: return this.salePrice() <= amount; so that the whole method becomes: // determine whether the given amount is enough to buy this book boolean enoughMoney(int amount) { return this.salePrice() <= amount; } 6. Tests: -- to be inserted in the ExamplesBooks class: boolean test4 = this.ch.enoughMoney(2000) == true; boolean test5 = this.dvc.enoughMoney(2000) == false; */ /* Finally, we want to figure out whether one book costs less than another one. 1. Problem analysis and data analysis: The method consumes one additional book and produces a boolean value. 2. Purpose and header: // determine whether this book is cheaper than the given book boolean cheaperThan(Book that) {...} 3. Examples: ch.cheaperThan(dcv) == true dvc.cheaperThan(ch) == false 4. Template: --- we can now add the methods we already defined --- ... this.title ... ... this.author ... ... this.price ... ... this.salePrice() ... ... this.enoughMoney(int amount) ... --- and also all these =fields and methods for 'that' book --- ... that.title ... ... that.author ... ... that.price ... ... that.salePrice() ... ... that.enoughMoney(int amount) ... The first part of the template should be retained at the end of the class as it grows as more methods are added to the class. It can be just copied and pasted into the method body as it is being developed, and erased once not needed. The second part is specific to this method, and so should be written there. 5. Body: return this.cheaperThan() <= that.salePrice(); so that the whole method becomes: // determine whether this book is cheaper than the given book boolean cheaperThan(Book that) { return this.salePrice() <= that.salePrice(); } 6. Tests: -- to be inserted in the ExamplesBooks class: boolean test6 = this.ch.cheaperThan(this.dvc) == true; boolean test7 = this.dvc.cheaperThan(this.ch) == false; */ /*Here is our code all together: +-------------------+ | Book | +-------------------+ | String title | | String author | | int price | | boolean hardcover | +-------------------+ */ // to represent a book in a bookstore class Book2 { String title; String author; int price; boolean hardcover; Book2(String title, String author, int price, boolean hardcover) { this.title = title; this.author = author; this.price = price; this.hardcover = hardcover; } // compute the sale price of this book int salePrice(){ if (this.hardcover) return this.price - this.price / 5; else return this.price; } // determine whether the given amount is enough to buy this book boolean enoughMoney(int amount) { return this.salePrice() <= amount; } // determine whether this book is cheaper than the given book boolean cheaperThan(Book2 that) { return this.salePrice() <= that.salePrice(); } } class ExamplesBooks2{ ExamplesBooks2() {} Book2 ch = new Book2("the Cat in a Hat", "Dr Seuss", 1500, true); Book2 dvc = new Book2("Da Vinci Code", "Dan Brown", 3000, true); Book2 cr = new Book2("Catcher in a Rye", "JD Salinger", 800, false); boolean test1 = this.ch.salePrice() == 1200; boolean test2 = this.dvc.salePrice() == 2400; boolean test3 = this.cr.salePrice() == 800; boolean test4 = this.ch.enoughMoney(2000) == true; boolean test5 = this.dvc.enoughMoney(2000) == false; boolean test6 = this.ch.cheaperThan(this.dvc) == true; boolean test7 = this.dvc.cheaperThan(this.ch) == false; }