CS61A Lab 7: Objected-Oriented Programming

Week 7, 2011


Warmup

0.) Predict the result of evaluating the following calls in the interpreter. Then try them out yourself!

>>> class Account(object):
...     interest = 0.02
...     def __init__(self, account_holder):
...         self.balance = 0
...         self.holder = account_holder
...     def deposit(self, amount):
...         self.balance = self.balance + amount
...         print("Yes!")
...
>>> a = Account("Billy")
>>> a.account_holder
______

>>> a.holder
______

>>> class CheckingAccount(Account):
...     def __init__(self, account_holder):
...         Account.__init__(self, account_holder)
...     def deposit(self, amount):
...         Account.deposit(self, amount)
...         print("Have a nice day!")
...
>>> c = CheckingAccount("Eric")
>>> a.deposit(30)
______

>>> c.deposit(30)
______

1.) Consider the following basic definition of a Person class:

class Person(object):

    def __init__(self, name):
        self.name = name

    def say(self, stuff):
        return stuff

    def ask(self, stuff):
        return self.say("Would you please " + stuff)

    def greet(self):
        return self.say("Hello, my name is " + self.name)

Modify this class to add a repeat method, which repeats the last thing said. Here's an example of its use:

>>> john = Person("John")
>>> john.repeat()       # starts at whatever value you'd like
"I squirreled it away before it could catch on fire."
>>> john.say("Hello")
"Hello"
>>> john.repeat()
"Hello"
>>> john.greet()
"Hello, my name is John"
>>> john.repeat()
"Hello, my name is John"
>>> john.ask("preserve abstraction barriers")
"Would you please preserve abstraction barriers"
>>> john.repeat()
"Would you please preserve abstraction barriers"

2.) Suppose now that we wanted to define a class called DoubleTalker to represent people who always say things twice:

>>> steven = DoubleTalker("Steven")
>>> steven.say("hello")
"hello hello"
>>> steven.say("the sky is falling")
"the sky is falling the sky is falling"
Consider the following three definitions for DoubleTalker:
class DoubleTalker(Person):
    def __init__(self, name):
        Person.__init__(self, name)
    def say(self, stuff):
        return Person.say(self, stuff) + " " + self.repeat()

class DoubleTalker(Person):
    def __init__(self, name):
        Person.__init__(self, name)
    def say(self, stuff):
        return stuff + " " + stuff

class DoubleTalker(Person):
    def __init__(self, name):
        Person.__init__(self, name)
    def say(self, stuff):
        return Person.say(self, stuff + " " + stuff)

Determine which of these definitions work as intended. Also determine for which of the methods the three versions would respond differently. (Don't forget about the repeat method!)

4.) Here are the Account and CheckingAccount classes from lecture:

class Account(object):
    """A bank account that allows deposits and withdrawals."""

    interest = 0.02

    def __init__(self, account_holder):
        self.balance = 0
        self.holder = account_holder

    def deposit(self, amount):
        """Increase the account balance by amount and return the new balance."""
        self.balance = self.balance + amount
        return self.balance

    def withdraw(self, amount):
        """Decrease the account balance by amount and return the new balance."""
        if amount > self.balance:
            return 'Insufficient funds'
        self.balance = self.balance - amount
        return self.balance


class CheckingAccount(Account):
    """A bank account that charges for withdrawals."""

    withdraw_fee = 1
    interest = 0.01

    def withdraw(self, amount):
        return Account.withdraw(self, amount + self.withdraw_fee)

Modify the code so that both classes have a new attribute, transactions, that is a list keeping track of any transactions performed. For example:

>>> eric_account = Account(“Eric”)
>>> eric_account.deposit(1000000)   # depositing my paycheck for the week
1000000
>>> eric_account.transactions
[(‘deposit’, 1000000)]
>>> eric_account.withdraw(100)      # buying dinner
999900
>>> eric_account.transactions
[(‘deposit’, 1000000), (‘withdraw’, 100)]

Don't repeat code if you can help it; use inheritance!

5.) We'd like to be able to cash checks, so let's add a deposit_check method to our CheckingAccount class. It will take a Check object as an argument, and check to see if the payable_to attribute matches the CheckingAccount's holder. If so, it marks the Check as deposited, and adds the amount specified to the CheckingAccount's total. Here's an example:

>>> check = Check(“Steven”, 42)  # 42 dollars, payable to Steven
>>> steven_account = CheckingAccount(“Steven”)
>>> eric_account = CheckingAccount(“Eric”)
>>> eric_account.deposit_check(check)  # trying to steal steven’s money
The police have been notified.
>>> eric_account.balance
0
>>> check.deposited
False
>>> steven_account.balance
0
>>> steven_account.deposit_check(check)
42
>>> check.deposited
True
>>> steven_account.deposit_check(check)  # can't cash check twice
The police have been notified.

Write an appropriate Check class, and add the deposit_check method to the CheckingAccount class. Make sure not to copy and paste code! Use inheritance whenever possible.

6.) If you finish the lab early, feel free to get started on the next project!