1
15-214
School of Computer Science
Charlie Garrod Michael Hilton School of Computer Science 15-214 - - PowerPoint PPT Presentation
Principles of Software Construction: Objects, Design, and Concurrency Part 1: Designing Classes Design for Reuse Charlie Garrod Michael Hilton School of Computer Science 15-214 1 Administrivia HW2 due Thursday Sep 14, 11:59 p.m.
1
15-214
School of Computer Science
2
15-214
3
15-214
– Item 15: Minimize mutability – Item 39: Make defensive copies when needed
– Item 16: Favor composition over inheritance – Item 17: Design and document for inheritance or else prohibit it – Item 18: Prefer interfaces to abstract classes
– Chapter 9. Use-Case Model: Drawing System Sequence Diagrams – Chapter 10. Domain Model: Visualizing Concepts
4
15-214
– Java-specific details for inheritance
– System-level reuse with libraries and frameworks
5
15-214
# Products Cost With reuse Without reuse
6
15-214
7
15-214
static void sort(int[] list, boolean ascending) { … boolean mustSwap; if (ascending) { mustSwap = list[i] < list[j]; } else { mustSwap = list[i] > list[j]; } … } interface Comparator { boolean compare(int i, int j); } final Comparator ASCENDING = (i, j) -> i < j; final Comparator DESCENDING = (i, j) -> i > j; static void sort(int[] list, Comparator cmp) { … boolean mustSwap = cmp.compare(list[i], list[j]); … }
Version A: Version B':
8
15-214
– e.g. here, the Sorter is delegating functionality to some Comparator
interface Comparator { boolean compare(int i, int j); } final Comparator ASCENDING = (i, j) -> i < j; final Comparator DESCENDING = (i, j) -> i > j; static void sort(int[] list, Comparator cmp) { … boolean mustSwap = cmp.compare(list[i], list[j]); … }
9
15-214
– e.g. here, the Sorter is delegating functionality to some Comparator
– Sorter can be reused with arbitrary sort orders – Comparators can be reused with arbitrary client code that needs to compare integers
interface Comparator { boolean compare(int i, int j); } final Comparator ASCENDING = (i, j) -> i < j; final Comparator DESCENDING = (i, j) -> i > j; static void sort(int[] list, Comparator cmp) { … boolean mustSwap = cmp.compare(list[i], list[j]); … }
10
15-214
public interface List<E> { public boolean add(E e); public E remove(int index); public void clear(); … }
11
15-214
public class LoggingList<E> implements List<E> { private final List<E> list; public LoggingList<E>(List<E> list) { this.list = list; } public boolean add(E e) { System.out.println("Adding " + e); return list.add(e); } public E remove(int index) { System.out.println("Removing at " + index); return list.remove(index); } …
The LoggingList is composed of a List, and delegates (the non- logging) functionality to that List
12
15-214
– E.g., the Comparator
13
15-214
14
15-214
public interface CheckingAccount { public long getBalance(); public void deposit(long amount); public boolean withdraw(long amount); public boolean transfer(long amount, Account??? target); public long getFee(); } public interface SavingsAccount { public long getBalance(); public void deposit(long amount); public boolean withdraw(long amount); public boolean transfer(long amount, Account??? target); public double getInterestRate(); }
15
15-214
public interface Account { public long getBalance(); public void deposit(long amount); public boolean withdraw(long amount); public boolean transfer(long amount, Account target); public void monthlyAdjustment(); } public interface CheckingAccount extends Account { public long getFee(); } public interface SavingsAccount extends Account { public double getInterestRate(); } public interface InterestCheckingAccount extends CheckingAccount, SavingsAccount { }
16
15-214
– Different kinds of objects can be treated uniformly by client code – Each object behaves according to its type
If today is the last day of the month: For each acct in allAccounts: acct.monthlyAdjustment();
17
15-214
public abstract class AbstractAccount implements Account { protected long balance = 0; public long getBalance() { return balance; } abstract public void monthlyAdjustment(); // other methods… } public class CheckingAccountImpl extends AbstractAccount implements CheckingAccount { public void monthlyAdjustment() { balance -= getFee(); } public long getFee() { … } }
18
15-214
public abstract class AbstractAccount implements Account { protected long balance = 0; public long getBalance() { return balance; } abstract public void monthlyAdjustment(); // other methods… } public class CheckingAccountImpl extends AbstractAccount implements CheckingAccount { public void monthlyAdjustment() { balance -= getFee(); } public long getFee() { … } }
protected elements are visible in subclasses an abstract class is missing the implementation of one
an abstract method is left to be implemented in a subclass no need to define getBalance() – the code is inherited from AbstractAccount
19
15-214
– java.lang.Object – Collections library
20
15-214
21
15-214
Collection List Set AbstractCollection AbstractList LinkedList Vector HashSet AbstractSequentialList AbstractSet Cloneable ArrayList “implements” “extends”
Interface Class AbstractClass
interfaces
22
15-214
– Object is the superclass of all Java classes
– One thing is a refinement or extension of another
– Fundamentally enables reuse – And modeling flexibility
23
15-214
– Write code once and only once – Superclass features implicitly available in subclass
– Accessing objects the same way, but getting different behavior – Subtype is substitutable for supertype class A extends B class A implements I class A extends B
24
15-214
– An abstract class is a convenient hybrid – A subclass specializes a class's implementation
25
15-214
public abstract class AbstractAccount implements Account { protected long balance = 0; public boolean withdraw(long amount) { // withdraws money from account (code not shown) } } public class ExpensiveCheckingAccountImpl extends AbstractAccount implements CheckingAccount { public boolean withdraw(long amount) { balance -= HUGE_ATM_FEE; boolean success = super.withdraw(amount) if (!success) balance += HUGE_ATM_FEE; return success; } } Overrides withdraw but also uses the superclass withdraw method
26
15-214
public class CheckingAccountImpl extends AbstractAccount implements CheckingAccount { private long fee; public CheckingAccountImpl(long initialBalance, long fee) { super(initialBalance); this.fee = fee; } public CheckingAccountImpl(long initialBalance) { this(initialBalance, 500); } /* other methods… */ } Invokes another constructor in this same class Invokes a constructor of the
first statement of the constructor.
27
15-214
– e.g., public final class CheckingAccountImpl { …
28
15-214
– e.g., double pi = 3.14; int indianaPi = (int) pi;
– e.g., Account acct = …; CheckingAccount checkingAcct = (CheckingAccount) acct; long fee = checkingAcct.getFee(); – Will get a ClassCastException if types are incompatible
– Never(?) downcast within superclass to a subclass
29
15-214
public void doSomething(Account acct) { long adj = 0; if (acct instanceof CheckingAccount) { checkingAcct = (CheckingAccount) acct; adj = checkingAcct.getFee(); } else if (acct instanceof SavingsAccount) { savingsAcct = (SavingsAccount) acct; adj = savingsAcct.getInterest(); } … }
– Never(?) use instanceof in a superclass to check type against subclass
30
15-214
public void doSomething(Account acct) { long adj = 0; if (acct instanceof CheckingAccount) { checkingAcct = (CheckingAccount) acct; adj = checkingAcct.getFee(); } else if (acct instanceof SavingsAccount) { savingsAcct = (SavingsAccount) acct; adj = savingsAcct.getInterest(); } else if (acct instanceof InterestCheckingAccount) { icAccount = (InterestCheckingAccount) acct; adj = icAccount.getInterest(); adj -= icAccount.getFee(); } … }
31
15-214
public interface Account { … public long getMonthlyAdjustment(); } public class CheckingAccount implements Account { … public long getMonthlyAdjustment() { return getFee(); } } public class SavingsAccount implements Account { … public long getMonthlyAdjustment() { return getInterest(); } }
32
15-214 public void doSomething(Account acct) { float adj = 0.0; if (acct instanceof CheckingAccount) { checkingAcct = (CheckingAccount) acct; adj = checkingAcct.getFee(); } else if (acct instanceof SavingsAccount) { savingsAcct = (SavingsAccount) acct; adj = savingsAcct.getInterest(); } … }
Instead:
public void doSomething(Account acct) { long adj = acct.getMonthlyAdjustment(); … }
33
15-214
– Inheritance violates information hiding
– Document requirements for overriding any method
34
15-214
– Extend behavior for new functionality
– Do no modify existing modules
35
15-214
36
15-214
37
15-214
– Strategy pattern
– Template method pattern – Iterator pattern – Decorator pattern (next Tuesday)
38
15-214
39
15-214
https://en.wikipedia.org/wiki/Gray%27s_Anatomy#/media/File:Gray219.png
40
15-214
http://www.davros.org/rail/diagrams/old_liverpool_street.gif
41
15-214
https://www.udel.edu/johnmack/frec682/cholera/snow_map.png
42
15-214
http://www.uh.edu/engines/epi1712.htm
43
15-214
http://files.www.ihshotair.com/twinny-s/0508- Machine_Base-CE_version.jpg
44
15-214
http://www.instructables.com/file/F7847TEFW4JU1UC/
45
15-214
46
15-214
47
15-214
48
15-214
49
15-214
50
15-214
– Sequence diagrams – Communication diagrams
51
15-214
public interface Account { public long getBalance(); public void deposit(long amount); public boolean withdraw(long amount); public boolean transfer(long amount, Account target); public void monthlyAdjustment(); } public interface CheckingAccount extends Account { public long getFee(); } public interface SavingsAccount extends Account { public double getInterestRate(); } public interface InterestCheckingAccount extends CheckingAccount, SavingsAccount { }
52
15-214
public abstract class AbstractAccount implements Account { protected long balance = 0; public long getBalance() { return balance; } abstract public void monthlyAdjustment(); // other methods… } public class CheckingAccountImpl extends AbstractAccount implements CheckingAccount { public void monthlyAdjustment() { balance -= getFee(); } public long getFee() { … } }