InheritancePrinciples of Software System ConstructionPrinciples of Software System ConstructionJonathan Aldrich Bill ScherlisSpring 2012Bank Accounts• What kind of accounts does a bank offer? What are their basic features?Fall 2011 15-214: Course Introduction 2Account Interfaces«interface» CheckingAccountgetBalance() : floatdeposit(amount : float)withdraw(amount : float) : booleantransfer(amount : float,target : Account) : booleangetFee() : float«interface» SavingsAccountgetBalance() : floatdeposit(amount : float)withdraw(amount : float) : booleantransfer(amount : float,target : Account) : booleangetInterestRate() : float• What do you think of this design?Fall 2011 15-214: Course Introduction 3getFee() : floatgetInterestRate() : floatAccount Type Hierarchy«interface» AccountgetBalance() : floatdeposit(amount : float)withdraw(amount : float) : booleantransfer(amount : float,target : Account) : booleanmonthlyAdjustment()SavingsAccount is a subtype of Account. Account is a supertype of SavingsAccount.CheckingAccountextends Account.All methods from Account are inherited (copied to CheckingAccount)Fall 2011 15-214: Course Introduction 4«interface» CheckingAccountgetFee() : float«interface» SavingsAccountgetInterestRate() : float«interface» InterestCheckingAccountMultiple interface extensionIf we know we have a CheckingAccount, additional methods are available.The Power of Object-Oriented Interfaces• Polymorphism– Different kinds of objects can be treated uniformly by clients• Keep a list of all accounts• Use accessor (getBalance) and mutator (deposit, transfer) methods– Each object behaves according to its type• monthlyAdjustment(): fee for checking, interest for savingsvoid adjustAll() {void adjustAll() {for (Account acct : getAllAccounts())acct.monthlyAdjustment()}• Impact– Add new kind of account: client code does not change– Important because this kind of change happens often!Fall 2011 15-214: Course Introduction 5Polymorphism is the key strength of OO• Difficult to encode in other paradigms and languages (C, ML, etc.)• Will come back repeatedly in this classImplementing Accounts• All 3 accounts similar– Same code for balance, deposit, withdraw, transfer– Differ in monthlyAdjustment– Differ in additional features•Duplication is bad«interface» AccountgetBalance() : floatdeposit(amount : float)withdraw(amount : float) : booleantransfer(amount : float,target : Account) : booleanmonthlyAdjustment()•Duplication is bad– Lots of code to type– Fix bugs 3 times– Make enhancements 3 times– Easily becomes inconsistent– What if another new account type is developed?• Design mantra: once and only once!Fall 2011 15-214: Course Introduction 6«interface» CheckingAccountgetFee() : float«interface» SavingsAccountgetInterestRate() : float«interface» InterestCheckingAccountReusing Account Codepublic abstract class AbstractAccountimplements Account {protected float balance = 0.0;public float getBalance() {return balance;}abstract public void monthlyAdjustment();// other methods…«interface» AccountgetBalance() : floatdeposit(amount : float)withdraw(amount : float) : booleantransfer(amount : float,target : Account) : booleanmonthlyAdjustment()AbstractAccountprotected elements are visible in subclassesan abstract class is missing the implemention of one or more methods}public class CheckingAccountImplextends AbstractAcountimplements CheckingAccount {public void monthlyAdjustment() {balance -= getFee();}public float getFee() { /* fee calculation */ }}Fall 2011 15-214: Course Introduction 7CheckingAccountImplmonthlyAdjustment()getFee() : floatAbstractAccount# balance : float+ getBalance() : float+ deposit(amount : float)+ withdraw(amount : float) : boolean+ transfer(amount : float,target : Account) : boolean+ monthlyAdjustment()«interface» CheckingAccountgetFee() : floatan abstract method is left to be implemented in a subclassno need to define getBalance() – the code is inherited from AbstractAccountInheritance vs. Subtyping• Inheritance– A class reuses code from a superclass• class A extends B– Inheritance is for code reuse• Write code once and only once• Code from superclass implicitly available in subclass• Subtyping– A class implements a (Java) interface• class A implements I– A class implements the (implicit) interface of another class• class A extends B : both subtyping and inheritance– Subtyping is for polymorphism• Accessing objects the same way, but getting different behavior• Subtype is substitutable for supertypeFall 2011 15-214: Course Introduction 8Challenge: Is Inheritance Necessary?• Can we get the same amount of code reuse using only interfaces?«interface» AccountgetBalance() : floatdeposit(amount : float)withdraw(amount : float) : booleantransfer(amount : float,target : Account) : booleanmonthlyAdjustment()Fall 2011 15-214: Course Introduction 9«interface» CheckingAccountgetFee() : float«interface» SavingsAccountgetInterestRate() : float«interface» InterestCheckingAccountReuse via Wrapping«interface» AccountgetBalance() : floatdeposit(amount : float)withdraw(amount : float) : booleantransfer(amount : float,target : Account) : booleanmonthlyAdjustment()requires a lot of forwardingFall 2011 15-214: Course Introduction 10«interface» CheckingAccountgetFee() : floatCheckingAccountImplmonthlyAdjustment() { … }getFee() : float { … }getBalance() : floatdeposit(amount : float)withdraw(amount : float) : booleantransfer(amount : float,target : Account) : booleanbasicAcnt.getBalance()BasicAccountImplbalance : floatgetBalance() : floatdeposit(amount : float)withdraw(amount : float) : booleantransfer(amount : float,target : Account) : booleanbasicAcntReuse via Wrapping, version 2«interface» AccountgetBalance() : floatdeposit(amount : float)withdraw(amount : float) : booleantransfer(amount : float,target : Account) : booleanmonthlyAdjustment()adjustmentaccountrequires two-way dependenceFall 2011 15-214: Course Introduction 11«interface» AdjustmentdoAdjust()SavingsAccountAdjustmentdoAdjust()adjustment.doAdjust()BasicAccountImplbalance : floatgetBalance() : floatdeposit(amount : float)withdraw(amount : float) : booleantransfer(amount : float,target : Account) : booleanmonthlyAdjustment()adjustmentaccountfloat bal = account.getBalance();float interest = bal * interestRate;account.deposit(interest);Inheritance vs. Delegation• The wrapping strategy described above is called
View Full Document