import tester.Tester; /* We want to represent an book with an author as data in DrRacket and then in Java. Here is the data definition in DrRacket: ;; to represent a book in a bookstore ;; A Book is (make-book String String Number) (define-struct book (title author price)) ;; Examples: (define htdp (make-book "HtDP" "FFFK" 60)) (define beaches (make-book "Beaches" "PC" 20)) We now want to define a function that will produce the book price on the day we have a sale. On the sale day, all books are discounted by the same percentage. ;; compute the sale price of a book for the given discount ;; sale-price: Book Num -> Num (define (sale-price abook disc) (- (book-price abook) (/ (* (book-price abook) disc) 100))) (check-expect (sale-price htdp 30) 42) (check-expect (sale-price beaches 20) 16) Note that these functions are useless for other types of data - they require that we provide a book. In Java all computations relevant for one type of data are defined as 'methods' in the class that represents the relevant data. We start by rewriting the above data definitions as a class diagram and defining the classes that represent books and examples of data and computation relavent for books: +---------------+ | Book | +---------------+ | String title | | Author author | | int price | +---------------+ The Java class definition that corresponds to this class diagram is shown below. */ // to represent a book in a bookstore class Book{ String title; String author; int price; // the constructor Book(String title, String author, int price){ this.title = title; this.author = author; this.price = price; /* TEMPLATE: ... this.title ... -- String ... this.author ... -- String ... this.price ... -- int Note that the template includes all fields defined in this class and specifies their types as well. We will etend the template in the subsequent examples. */ /* The method definition comes here We follow the design recipe. We start with a comment, a purpose statement, then write the contract and the header. here they are combined into one line that specifies the name of the method, the type of value that the method will produce, and includes not only the list of parameter names, but for each it speciies its data type as well. There is no 'Book' parameter - only objects of the type Book are allowed to ask what is their sale price. We say that an instance of the Book class (or object of the type Book) invokes the methods defined in the Book class. The examples are shown below and show that each method evaluation request is preceeded by the book object for which the computation should be made. This object acts as an implicit argument for the method --- the method has access to all fields of this object and refers the the object with the keyword 'this'. The helps us in building the template -- shown above. All methods defined in the Book class will have the same basic template - and so we write the template as a block comment right after the constructor for this class, before all method definitions. */ // compute the sale price of this book given today's discount // in percent of the priginal price int salePrice(int discount){ return this.price - (this.price * discount) / 100; } // } // examples and tests for the class hierarchy that represents // books and authors class ExamplesBooks{ ExamplesBooks(){} Book htdp = new Book("HtDP", "FFK", 60); Book beaches = new Book("Beaches", "PC", 20); /* The tests are defined as methods that produce a boolean value that indicates whether the test passed. We need to add an 'import' statement on the top of the file that indicates that we will use the tester library. The library evaluates the checkExpect methods that consume two values and produces true or false depending on whether the two values are the same. */ // test the method salePrice for the class Book boolean testSalePrice(Tester t){ return t.checkExpect(this.htdp.salePrice(30), 42) && t.checkExpect(this.beaches.salePrice(20), 16); } /* We can now run our program and see thet est results. */ }