CS61A Lab 8: Object Oriented Programming

Week 4B, 2012


1. 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)
________

2. 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:

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

3. 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:

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

# 3
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 - amount:
            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
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 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 CheckincAccount class. Make sure not to copy and paste code! Use inheritance whenever possible.