Welcome to Programming Languages...
Transcript of Welcome to Programming Languages...
Welcome to Programming Languages (ITP20005)
• lab08 - OOP• Due is 09:59, Nov. 25, 2014 (One week from today)• lab08.pdf (No template file provided)• 3.5 points (2~6: 0.5 point each, 7: 1.0 point)
In the beginning God created the heavens and the earth.
ITP 20005 Programming LanguagesChapter 2 Building Abstractions with Data
Major references: 1. Structure and Interpretation of Computer Programs(SICP) by Abelson and Sussman, MIT
Composing Programs by John DeNero, Google2. MITx OPENCOURSEWARE(OCW) 6.00 SC Lecture 3. UC Berkley CS61A Lecture 4. Python, Wikipedia and many on-line resources.Prof. Youngsup Kim, [email protected], 2014 Programming Languages, CSEE Dept., Handong Global University
5. Object-Oriented Programming 1. Classes2. Object3. Attributes4. Methods5. Inheritance
4
Object
Object-Oriented Programming
Classes
instance 1instance 2instance 3……
method Amethod Bmethod C
……
attribute aattribute battribute c
……
Review
5
Terminology: Attributes, Functions, and Methods
• All objects have attributes, which are name-value pairs.
• Classes are objects too, so they have attributes.
• Instance attributes: attributes of instance objects.
• Class attributes: attributes of class objects.
Terminology:
ClassAttributes
FunctionsMethods
Python object system:
Functions are objects.
Bound methods are also objects: a function that has its first parameter "self" already bound to an instance.
Dot expressions evaluate to bound methods for class attributes that are functions.
<instance>.<method_name>
6
Inheritance
everywhere…everything…except…
God created man in his own image, in the image of God he created him;
Genesis 1:27 f
7
Inheritance
• Inheritance is a method for relating classes together.
• A common use: Two similar classes differ in their degree of specialization.
• The specialized class may have the same attributes as the general class, along with some special-case behavior.
• Conceptually, the new subclass "shares" attributes of its base class.
class <Name>(<Base Class>):
<suite>
• The subclass may override certain inherited attributes.
• Using inheritance, we implement a subclass by specifying its differences from the base class.
8
Inheritance Example
A CheckingAccount is a specialized type of Account.
Let's review the class Account since ...
Challenge: Implement a CheckingAccount.
Characteristics?
9
Methods are functions defined in the suite of a class statement.
class Account:
def __init__(self, account_holder):
self.balance = 0
self.holder = account_holder
def deposit(self, amount):
self.balance = self.balance + amount
return self.balance
def withdraw(self, amount):
if amount > self.balance:
return 'Insufficient funds'
self.balance = self.balance - amount
return self.balance
self should always be bound to an instance of the Account class
These def statements create function objects as always,but their names are bound as attributes of the class
Review
10
Inheritance Example
Challenge: Implement a CheckingAccount.
• account holder – same as a regular account • balance – same• interest rate – a little lower than a regular account• deposit – same • withdraw – may have a fee
Characteristics?
11
Inheritance Example
A CheckingAccount is a specialized type of Account.
Most behaviors are shared with the base class Account.
>>> ch = CheckingAccount('Tom')
>>> ch.interest # Lower interest rate for checking accounts
0.01
>>> ch.deposit(20) # Deposits are the same
20
>>> ch.withdraw(5) # Withdrawals incur a $1 fee
14
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)
return super().withdraw(self, amount + self.withdraw_fee)
or
12
Base class attributes aren't copied into subclasses!
Looking Up Attribute Names on Classes
To look up a name in a class:
1. If it names an attribute in the class, return the attribute value.
2. Otherwise, look up the name in the base class, if there is one.
>>> ch = CheckingAccount('Tom') # Calls Account.__init__
>>> ch.interest # Found in CheckingAccount
0.01
>>> ch.deposit(20) # Found in Account
20
>>> ch.withdraw(5) # Found in CheckingAccount
14
[Demo]
13
Object-Oriented Design
14
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)
Designing for Inheritance
• Don't repeat yourself; use existing implementations.
• Attributes that have been overridden are still accessible via class objects.
• Look up attributes on instances whenever possible.
Attribute look-up on base class
15
Inheritance vs
16
Inheritance
having another objects as attributes
Compositionvs
17
Inheritance and Composition
Object-oriented programming shines when we adopt the metaphor.
Inheritance is best for representing is-a relationships.
• E.g., a checking account is a specific type of account.
• So, CheckingAccount inherits from Account.
Composition is best for representing has-a relationships.
• E.g., a bank has a collection of bank accounts it manages.
• So, A bank has a list of accounts as an attribute.
[Demo]
18
Inheritance and Composition
class Bank:
""" A bank *has* accounts.
class Account:
def __init__(self, account_holder):
self.balance = 0
self.holder = account_holder
// more attributes follows ...
Is this relation is-a or has-a?
19
Inheritance and Composition
class Bank:
""" A bank *has* accounts.
>>> bank = Bank()
>>> john = bank.open_account('John', 10)
>>> jack = bank.open_account('Jack', 5, CheckingAccount)
>>> john.interest
0.02
>>> jack.interest
0.01
>>> bank.pay_interest()
>>> john.balance
10.2
"""
def __init__(self):
self.accounts = []
def open_account(self, holder, account_type=Account):account = account_type (holder)account.deposit(amount)
self.accounts.append(account)
return account
def pay_interest(self):
for a in self.accounts:
a.deposit(a.balance * a.interest)
20
Inheritance and Composition
class Bank:
""" A bank *has* accounts.
>>> bank = Bank()
>>> john = bank.open_account('John', 10)
>>> jack = bank.open_account('Jack', 5, CheckingAccount)
>>> john.interest
0.02
>>> jack.interest
0.01
>>> bank.pay_interest()
>>> john.balance
10.2
>>> bank.too_big_to_fail()
True
"""
def __init__(self):
self.accounts = []
def open_account(self, holder, account_type=Account):account = account_type (holder)account.deposit(amount)
self.accounts.append(account)
return account
def pay_interest(self):
for a in self.accounts:
a.deposit(a.balance * a.interest)
def too_big_to_fail(self):
return len(self.accounts) > 1
21
Multiple Inheritance
22
Multiple Inheritance
class SavingsAccount(Account):
deposit_fee = 2
def deposit(self, amount):
return Account.deposit(self, amount - self.deposit_fee)
A class may inherit from multiple base classes in Python.
CleverBank marketing executive has an idea:Example:
• Low interest rate of 1%• A $1 fee for withdrawals• A $2 fee for deposits• A free dollar when you open your account
class AsSeenOnTVAccount(CheckingAccount, SavingsAccount):
def __init__(self, account_holder):
self.holder = account_holder
self.balance = 1 # A free dollar!
23
A class may inherit from multiple base classes in Python.
class AsSeenOnTVAccount(CheckingAccount, SavingsAccount):
def __init__(self, account_holder):
self.holder = account_holder
self.balance = 1 # A free dollar!
Multiple Inheritance
>>> such_a_deal = AsSeenOnTVAccount("John")
>>> such_a_deal.balance
1
>>> such_a_deal.deposit(20)
19
>>> such_a_deal.withdraw(5)
13
Instance attribute
SavingsAccount method
CheckingAccount method
24
>>> such_a_deal = AsSeenOnTVAccount("John")
>>> such_a_deal.balance
1
>>> such_a_deal.deposit(20)
19
>>> such_a_deal.withdraw(5)
13
Resolving Ambiguous Class Attribute Names
Instance attribute
SavingsAccount method
CheckingAccount method
CheckingAccount SavingAccount
Account
AsSeenOnTVAcount
25
class CheckingAccount(Account):
withdraw_fee = 1
def withdraw(self, amount):
return Account.withdraw(self, amount + withdraw_fee)
Challenge: What’s wrong in the following?
Looking up names
Name expressions look up names in the environment:
<name>
Dot expressions look up names in an object:
<expression> . <name>
Error: withdraw_fee not bound in environment
Not all languages work this way.
26
CheckingAccount SavingAccount
Account
AsSeenOnTVAcount
Resolving Ambiguous Class Attribute Names
class AsSeenOnTVAccount(CheckingAccount, SavingsAccount):
• Methods looked up from bottom to top, left to right.
• The mro method on a class lists the order in which classes are checked for attributes. (mro stands for method resolution order.)
>>> [c.__name__ for c in AsSeenOnTVAccount.mro()]
['AsSeenOnTVAccount', 'CheckingAccount', 'SavingsAccount',
'Account', 'object']
27
Odds and Ends
The object class is at the root of the inheritance hierarchy.
• object should be given as the base class when no other meaningful base class exists
• Class names should be in CamelCase , not enforced.
Error messages can be confusing when calling methods with the wrong number of arguments:
>>> tom_account = Account('Tom') >>> tom_account.deposit(100, 200) TypeError: deposit() takes exactly 2 positional arguments (3 given)
Compare to partially curried function:
>>> add3 = curry(add)(3) >>> add3(4, 5)
TypeError: op_add expected 2 arguments, got 3
28
Resolving Ambiguous Class Attribute Names
Multiple Inheritance is complicated.
avoid it whenever possible!