CS21 Lab 11: Classes and Objects
Complete the Book class: Friday, April 21st, by 11:59pm
Complete the entire lab: Saturday, April 29th, by 11:59pm
Please read through the entire lab before starting!
Goals
-
Gain experience writing classes
-
Gain experience reading and using classes
1. Requirements
This is a two-week lab on object-oriented programming. In this lab, you will build an e-reader called the Swindle (any resemblance to current e-readers is completely coincidental).
You will use object-oriented programming to create two classes split into two parts described below.
1.1. Part 1: Complete the Book class
-
The first class you will develop is the
Book
class that encapsulates one electronic book (or ebook). We have made several free ebooks available for you to load and experiment with once you get your Book class working. -
For the first handin, you will need to have a complete working version of
book.py
. Details on getting started are listed in the section on theBook
class.
1.2. Part 2: Build an e-reader
-
The second class you will develop is the
Swindle
class that encapsulates the concept of an e-reader. You will be able to perform several core operations of an e-reader, including:-
buying books,
-
picking a book from your virtual shelf, and
-
reading a book.
-
-
You will also be responsible for error handling, detailed descriptions of the types of errors are presented in the section on the
Swindle
class.
2. Getting Started
To get started, take note of the files that we have provided for you.
You need to complete the following:
-
book.py
- the definition of the Book class to be completed by you. -
swindle.py
- the definition of the Swindle class to be completed by you (we give you a partially implemented constructor and a few other completed methods).
The following files do not require any changes:
-
bookdb.txt
- a file containing information about all of the books available for download. -
ereader.py
- the main program to create a Swindle and interact with the device (we give you all of this).
2.1. Example Output
Here are several sample runs.
2.1.1. Sample run for book.py
(for the Part 1 deliverable)
2.1.2. Sample runs of the entire lab (for Part 2 deliverable)
Read through this carefully so that you can see how the e-reader should operate, and understand which parts you need to implement and which parts are already implemented for you.
3. Top-Down Design
-
Continue to use top-down design. As the first step, you should stub out the entire class definition for
Book
andSwindle
Classes. -
All methods (except getters and setters) should have a triple-quoted comment explaining their input parameters, return value, and purpose.
-
Each method should have a print statement. If a method returns a value, it should return a dummy value of the correct type.
-
Use bottom-up implementation and thoroughly test each method as you complete it.
You should be incrementally testing your code! You should not wait until you have implemented every method before you begin testing. |
Lab instructors, ninjas and (graders!) will expect to see you practicing these good top-down design techniques.
4. Complete the Book class
A Book
object represents an electronic book to read on your e-reader. You should define your class such that each book maintains the following data (also called instance variables):
-
title (string) — the title of the book
-
author (string) — the author of the book
-
year (int) — the year the book was published
-
filename (string) — where the book is stored on disk, for example:
/usr/local/doc/alice.txt
-
bookmark (int) — the page number where the owner left off when last reading the book.
Your Book
class should define the following methods:
-
_init_:
constructor that initializes aBook
object, where the parameters specify the title, author, year published, and the name of the file containing the book.-
You should initialize all data fields for the object in this function.
-
Remember to use
self.
(self followed by the period.
) in front of every data field associated with the class. -
The bookmark data field for a newly created
Book
object should be initialized to page zero, since it’s a new book.
-
-
toString:
method that returns a string representation of aBook
object.-
Your method should return a string containing the title, author, and date published in a readable format.
-
Use string formatting to give the title a width of 25 and the author a width of 20. When you print information about multiple books, this will line the book information up nicely as shown below:
Alice in Wonderland by Lewis Carroll (1865) Gettysburg Address by Abe Lincoln (1863)
-
-
Your
Book
class should have getter methods for all of the object’s data (for example:getTitle()
,getAuthor()
, etc. You can look at the sample runs to get an idea of what these should look like. -
Both getter and setter methods for the object’s bookmark data.
-
getText():
method to retrieve the entire contents of the book as a single string. This method will need to:-
Open the filename stored in the Book object
-
Ignore any lines in the file that start with a pound sign (#)
-
Store all lines of the file in one long string (do not remove newline characters!).
-
Close the file
-
-
For example, if the file contained Pride and Prejudice:
# The Project Gutenberg EBook of Pride and Prejudice, by Jane Austen # (#8 in our series by Jane Austen) # # Copyright laws are changing all over the world. Be sure to check the # copyright laws for your country before downloading or redistributing ... [more lines beginning with pound sign] ... # *** START OF THE PROJECT GUTENBERG EBOOK, PRIDE AND PREJUDICE *** Pride and Prejudice by Jane Austen Chapter 1 It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife. .... [more text] ....
Then
getText()
would return a string where the lines starting with the pound sign have been removed. When you print this string, it will look like as follows:Pride and Prejudice by Jane Austen Chapter 1 It is a truth universally acknowledged, that a single man in possession of a good fortune, must be in want of a wife. .... [more text] ....
Notice that getText()
preserves the white space and newline characters in the text. Only the lines with the pound sign have been removed.
4.1. Incrementally test the Book class
As you complete each method of the Book
class you should test it. Notice that at the bottom of your book.py
file we have provided a suite of tests. You should convince yourselves that these tests, are complete, by comparing it against the example output
|
5. Complete the Swindle class
The Swindle
class defines an e-reader device. Every instance must maintain a few pieces of data:
-
owner (string) — the owner’s name
-
availableBooks (list of
Book
objects) — books available for sale -
ownedBooks (list of
Book
objects) — books owned by the user -
page length (int) - the number of lines to display per page; 20 is a good default page length.
5.1. The constructor
We have provided the beginning of the class definition by defining the constructor (which includes the functionality for loading the database of available books). You only need to add a few lines of code where you see the following comment:
# TODO: using the information just obtained from the file,
# create a Book object with this data and add it to the
# availableBooks list
-
When first creating a Swindle object, the user does not own any books, and all books in the database should be considered books available for purchase.
-
It is important to note that both the variables
availableBooks
andownedBooks
are lists ofBook
objects. Here is a clear example of the power of encapsulation! -
A Book object stores all of the important information and functionality needed to interact with a book. By keeping lists of
Book
objects, theSwindle
class can easily implement the functionality for reading these books.
5.2. Methods provided for you to display a book
-
We have also provided the methods
displayText()
,displayPage()
, andgetLetter()
. These methods take care of the details involved in displaying a certain number of lines from the book. You do not need to change these methods. -
The method
displayText()
is the method you will call to allow the user to read one of their books. -
This method calls the method
displayPage()
to show a single page at a time. -
It also calls the method
getLetter()
to determine what the user wants to do next. -
Once the user decides to quit reading a particular book, the
displayText()
method returns the current page number of the book.
5.3. Methods you must implement
Your Swindle
class should define the following methods:
-
showOwned()
: prints all owned titles (see sample output below) -
showAvailable()
: prints all available (but not owned) titles -
getOwner()
: returns the owner’s name -
buy()
: allows the user to purchase a book. This method should print all available titles and allow the user to choose one book.
use the
|
-
read()
: allows the user to choose a book to read. This method should print all owned books and allow the user to choose one book.Use the showOwned()
method as a helper. It then calls the` displayText()` method, using the appropriate Book object as an argument todisplayText()
. When the user quits reading a book, set the bookmark to the current page, and print a message verifying that the bookmark was set.
For both the buy()
and read()
methods, you should ensure that the user selects a valid book number from the menu. You can assume that the user always enters an integer.
5.4. Incrementally test the Swindle class
As you complete each method of the Swindle
class you should test it. Notice that at the bottom of your swindle.py
file we have provided some initial tests. When you run $ python3 swindle.py` this test code will be executed.
if __name__ == '__main__':
print("="*50)
print("Test 1:Testing the Swindle class")
myswindle = Swindle()
print("="*50)
print("Test 2:Testing showAvailable()")
myswindle.showAvailable()
print("="*50)
print("Test 3:Testing showOwned()")
myswindle.showOwned()
#TODO: Write additional tests below
6. Putting it all together
Once you have written (and thoroughly tested!) the Book
and Swindle
classes, according to the above requirements, you should be able to successfully run the main ereader program:
$ python3 ereader.py
.
-
Take a look at the sample run demonstrating how the ereader should behave.
-
Test out all of features of your classes by trying every possible menu option from the ereader. Be sure to gracefully handle the following edge cases:
-
when the user wants to buy books, but none are available.
-
when the user wants to read books, but none are available.
-
7. Optional Enhancements
This section is completely optional. Feel free to attempt this once you have successfully completed all of the required portions of the lab. Because this is optional extension, we are leaving a lot of the details for you to figure out on your own.
If you wish to attempt this part, be sure to make copies of your orignal code as shown below. Only modify the copies, leaving the original solution alone.
$ cd cs21/labs/11
$ cp swindle.py enhancedSwindle.py
$ cp ereader.py enhancedEreader.py
The original version of the ereader starts from scratch every time, which is unrealistic. Instead, we would like the ereader to remember the owner’s name, the books that have been purchased (and what page number the owner is on), as well as the books that are still available.
To accomplish this you will need to learn how to write to a file. Below is a short example program showing how to do this:
def main():
name = "Sedi"
age = 21
fp = open("test.txt", "w")
fp.write("%s is %d years old\n" % (name, age))
fp.write("this is a test\n")
fp.write("here's another line\n")
fp.write("goodbye\n")
fp.close()
main()
Here’s what the file test.txt
would now contain:
Sedi is 21 years old
this is a test
here's another line
goodbye
One other new python feature you’ll need is to be able to check whether a particular file exists or not. You can try this in the python intepreter:
$ python3
>>> from os.path import isfile
>>> isfile("ereader.py")
True
>>> isfile("foobar")
False
Now that you know how to write a file and how to check whether a file exists, you are ready to implement the enhanced ereader. The basic idea is as follows:
-
Every time the user quits the ereader, write out a status file that stores all of the relevant information about the ereader. You can decide on the format for this status file.
-
When you start up the ereader, check if this status file exists.
-
If not, everything works as it did in the original ereader; you’ll need to read in the available books from the file
bookdb.txt
. -
If it does exist, welcome the owner back and read in the status information from the file you created (you can ignore the file
bookdb.txt
).
-
Without too much effort you’ll have an enhanced ereader that is much more like an actual device.
Answer the Questionnaire
Each lab will have a short questionnaire at the end. Please edit
the Questions-11.txt
file in your cs21/labs/11
directory
and answer the questions in that file.
Once you’re done with that, you should run handin21
again.
Submitting lab assignments
Remember to run handin21
to turn in your lab files! You may run handin21
as many times as you want. Each time it will turn in any new work. We
recommend running handin21
after you complete each program or after you
complete significant work on any one program.
Logging out
When you’re done working in the lab, you should log out of the computer you’re using.
First quit any applications you are running, like the browser and the terminal. Then click on the logout icon ( or ) and choose "log out".
If you plan to leave the lab for just a few minutes, you do not need to log out. It is, however, a good idea to lock your machine while you are gone. You can lock your screen by clicking on the lock icon. PLEASE do not leave a session locked for a long period of time. Power may go out, someone might reboot the machine, etc. You don’t want to lose any work!