1 CSD Univ. of Crete Fall 2008 Applying Inheritance to Solve problems.
-
Upload
alvin-thornton -
Category
Documents
-
view
219 -
download
3
Transcript of 1 CSD Univ. of Crete Fall 2008 Applying Inheritance to Solve problems.
1
CSD Univ. of Crete Fall 2008
Applying Inheritance to Solve problems
2
CSD Univ. of Crete Fall 2008
Classification, Generalization and Specialization
Classification the act of identifying and categorizing similar objects into
classes is known as classification the resulting categories are known as classes which form
meaningful abstractions for organizing information
Objects Roles Objects Roles
J ulia a customer Peter a salesperson
Angela a secretary J ohn a manager
Lawrence a salesperson Chris a customer
Alex a customer Anna a manager
List of people objects in a furniture shop
3
CSD Univ. of Crete Fall 2008
Classification, Generalization and Specialization
Customer- Alex- Julia- Chris
SalesPerson
- Lawrence- Peter
Manager
- John- Anna
Secretary
- Angela
4
CSD Univ. of Crete Fall 2008
Classification, Generalization and Specialization
Generalization generalization is the act of capturing similarities between classes
and defining the similarities in a new generalized class the original classes are known as subclasses, and the generalized
class is known as superclass
SalesPerson
- Lawrence- Peter
Manager
- John- Anna
Secretary
- Angela
Employee superclass
5
CSD Univ. of Crete Fall 2008
Classification, Generalization and Specialization
Specialization specialization is the act of capturing differences among objects in
a class and creating new distinct subclasses with the differences
Customer- Alex- Julia- Chris
Employee
PeopleInFS
subclass
6
CSD Univ. of Crete Fall 2008
Classification, Generalization and Specialization
Super- and sub-classes can be organized into a class hierarchy with the superclasses placed toward the top of the hierarchy and the subclasses toward the bottom of the hierarchy
which class an object is referred to in a class hierarchy is a matter of generality
PeopleInFS
Customer Employee
SalesPerson Manager Secretary
superclass
superclass andsubclass
subclass
7
CSD Univ. of Crete Fall 2008
Inheritance Example: People in Furniture Shop
PeopleInFS
Customer Employee
SalesPerson Manager Secretary
namegetName( )
nameemployeeNumgetName( )getEmployeeNum()
nameemployeeNumcommissiongetName( )
getEmployeeNum( )getCommission( )
takeOrder( )
nameaddressbudget
getName( )getBudget( )placeOrder( )
8
CSD Univ. of Crete Fall 2008
Customer- address: String- budget: int
+ getBudget( ): int+ placeOrder( ): void
PeopleInFS- name: String
+ getName( ): String
Employee- employeeNum: int
+ getEmployeeNum( ): int
SalesPerson- commission: int
+ getCommission( ): inttakeOrder( ): int
Manager
- allowance: int
+ getAllowance( ): int
Secretary
“inherits from ”(or “is-a ”)
Inheritance Example: People in Furniture Shop
9
CSD Univ. of Crete Fall 2008
- employeeNum: int
SalesPerson
- commission: int
+ getCommission( ): int+ takeOrder( ): int
- name: String
Employee
PeopleInFS
+ getEmployeeNum( ): int
+ getName( ): String
Inheritance Example: People in Furniture Shop
10
CSD Univ. of Crete Fall 2008
subclass
or
derived class
superclass
or
base class
extends
Inheritance and Java Classes/Interfaces
subinterface superinterfaceextends
class interfaceimplements
11
CSD Univ. of Crete Fall 2008
Applied Inheritance
Decide on the classes involved from the problem descriptionGroup classes into conceptually equivalent groupsPer group of classes, the generalizing concept will be a Parent to
those classes Distribute responsibilities amongst all classes based on what is
appropriate and customary for that class
Example: A program to teach geometry needs to model some basic shapes
All shapes have surface area, could have volume and locationThe shapes that need to be modeled are: Circle, Rectangle, Sphere,
Cylinder, and a Square
What classes will you need?
12
CSD Univ. of Crete Fall 2008
Classes: Circle, Rectangle, Sphere, Cylinder, Square, Coordinate
All “Shapes”
Square is a Rectangle
Coordinate
3D Shapes
2D Shapes
Inheritance hierarchy
Group classes
Shape
Shapes2D Shapes3D
Circle Rectangle
Square
Cylinder Sphere
Circle
Rectangle
SquareCylinder
Sphere
A Geometry Example
13
CSD Univ. of Crete Fall 2008
Shape
Shapes2D Shapes3D
Circle Rectangle
Square
Cylinder Sphere
Distribute Responsibilities:
Shape
+getSurfaceArea()+clone()+equals()+toString()+Object getLocation()
Shape2D
+ ?
Shape3D
+getVolume()
Is Shape2D needed?
A Geometry Example
14
CSD Univ. of Crete Fall 2008
public abstractabstract class Shape{ double getSurfaceArea(); Object getLocation(); Object clone(); String toString(); boolean equals();}
Observe the syntax of ShapeThe methods are not virtual methods
Abstract Class: A class with at least
one unimplemented method
Interface: A class with only
unimplemented methods
.public interfaceinterface Shape{ double getSurfaceArea(); Object getLocation(); Object clone(); String toString(); boolean equals();}
Example … Abstract classes
15
CSD Univ. of Crete Fall 2008
Q: How do you inherit from an interface?
A: By implementing the interface
public interface Shape implementsimplements Cloneable{ ...} public abstract class Shape2D implementsimplements Shape{ ...}
Q: How do you inherit from an Abstract class?
A: The usual way, by extending
public class Circle extendsextends Shape2D{…}
Sample Interfaces
16
CSD Univ. of Crete Fall 2008
public interface Shape extendsextends Clonable{ …}public abstract class Shape2D implementsimplements Shape{ … }public class Circle extendsextends Shape2D{
}
Circle has to implement all unimplemented methods of• 2DShape• Shape• Clonable
Its All Still Inheritance!
17
CSD Univ. of Crete Fall 2008
Client Code…Circle c = new Circle();… Shape s = c;
Cloneable cln = s;
Shape2D s2d = s;
Through cc you can access ALL methods
of CircleCircle AND its parents!
Through ss you can access ONLY methods
of ShapeShape and CloneableCloneable implemented in
CircleCircleThrough clncln you can access ONLY methods
of CloneableCloneable implemented in CircleCircle
Through s2d s2d you can access ONLY
methods of ShapeShape, CloneableCloneable, and
Shape2DShape2D implemented in CircleCircle
Its All Still Inheritance!
18
CSD Univ. of Crete Fall 2008
public class Rectangle extends Shape2D{
private int width,length;
public Rectangle(int w,int l){
width = w;
length = l;
}
public int getSurfaceArea(){
return(width*length);
}
The Class Rectangle
19
CSD Univ. of Crete Fall 2008
public boolean equals(Object o){
if(!o instanceOf Rectangle)
return false
Rectangle r = (Rectangle)o;
if (this.width != r.width)
return false;
if (this.length!=r.length)
return false;
return true;
}
The Class Rectangle
20
CSD Univ. of Crete Fall 2008
public void toString(){
System.out.println(“Rectangle”+width+” “+length);
}
public Object clone(){
return(new Rectangle(width,length);
}
public Object getLocation(){
…
}
The Class Rectangle
21
CSD Univ. of Crete Fall 2008
public abstract class ShapePair extends Shape{
private Shape shape1,shape2;
public ShapePair(Shape s1,Shape s2){
shape1 = s1;
shape2 = s2;
}
public int getSurfaceArea(){
return(shape1.getSurfaceArea() +shape2.getSurfaceArea());
}
The Class ShapePair
22
CSD Univ. of Crete Fall 2008
public Object clone(){
Shape s1 = (Shape)shape1.clone();
Shape s2 = (Shape)shape2.clone();
return(new ShapePair(s1,s2);
}
A very simple example of grouping two shapes!
The Class Rectangle
23
CSD Univ. of Crete Fall 2008
Understanding Polymorphism
Static vs dynamic binding binding refers to the association of a method invocation and the code
to be executed on behalf of the invocation in static binding, all the associations are determined at compile time
conventional function calls are statically bound
char shapeType[numShapes];struct circle circles[numCircles];struct square squares[numSquares];int c = 0, s = 0;...for (i = 0; i < numShapes; i++) switch (shapeType[i]) { ‘c’: calculateCircleArea(circles[c++]); break; ‘s’: calculateSquareArea(squares[s++]); break; }
24
CSD Univ. of Crete Fall 2008
Understanding Polymorphism
in dynamic binding, the code to be executed in response to a method invocation (i.e., a message) will not be determined until runtime method invocations to variable shapeArray (in the following
example) are dynamically boundpublic class ShapeDemoClient { public static void main(String argv[ ]) { Circle c1 = new Circle("Circle C1"); Circle c2 = new Circle("Circle C2", 3.0f); Square s1 = new Square("Square S1"); Square s2 = new Square("Square S2", 3.0f); Shape shapeArray[ ] = {c1, s1, c2, s2}; for (int i = 0; i < shapeArray.length; i++) { System.out.println("The area of " + shapeArray[i].getName( ) + " is " + shapeArray[i].calculateArea( ) + " sq. cm."); } } // End main} // End ShapeDemoClient1 class
25
CSD Univ. of Crete Fall 2008
Avoid Confusion Between Is-A and Has-A
Improper class hierarchies are commonly created when designers confuse is-a with has-a
“is-a” relation: the extension creates a new class that is kind of the original class, e.g,
“has-a” relation: an object of one class uses objects of other classes to store state or do work
A vehicle is-a Movable Abstraction A vehicle is-a Physical Abstraction A vehicle has-a location A vehicle is-not-a Point (the class of location)
Rectangle
Square
circle point1*
26
CSD Univ. of Crete Fall 2008
Composition versus Inheritance
All aspects of the protocol are part of child’s interface
Requires us to explicitly send messages to the class
Restricts operations on child to those that are applicable
Creates an independent type
Makes the use of the parent structure an implementation detail that can easily be changed
Requires us to look at the parent’s as well as child’s protocol
Reuses the parent’s code with no explicit references
Allows all the parent operations to be applied, even those that are meaningless for the child
Allows us to use the child anywhere the parent can be used
Ties the child to choice of the parent structure
27
CSD Univ. of Crete Fall 2008
BankAccount hierarchy
Object
BankAccount
JointBankAccount
Every Java class inherits from the top level Object class.The Object class is the ultimate parent of every Java class
We will write thisclass later
28
CSD Univ. of Crete Fall 2008
BankAccount Examples
Declare two accountsBankAccount fred = new
BankAccount(123, "Fred", 345.50);
JointBankAccount fredMary = new
JointBankAccount(345, "Fred", "Mary", 450,65);
A joint account is a type of account:BankAccount ellenFrank = new
JointBankAccount(456, "Ellen", "Frank", 3450);
The following statement is illegalJointBankAccount fred = new
BankAccount(123, "Fred", 345.50);
29
CSD Univ. of Crete Fall 2008
BankAccount Examples
Consider the two accountsJointBankAccount fredMary = new
JointBankAccount(345, "Fred", "Mary", 450,65);
BankAccount ellenFrank = new
JointBankAccount(456, "Ellen", "Frank", 3450);
The following statements are legalString owner = fredMary.getOwner();
String jointOwner = fredMary.getJointOwner();
The 2nd statement is illegalString owner = fredMary.getOwner();
String jointOwner = ellenFrank.getJointOwner();
30
CSD Univ. of Crete Fall 2008
AccountReader Example
Problem: Write an AccountReader class that can read both BankAccount and JointBankAccount objects.
Suggests that we need two methods with prototypespublic BankAccount readBankAccount()
public JointBankAccount readJointBankAccount()
Because of polymorphism only the first version is needed: a joint account "is an" account.
31
CSD Univ. of Crete Fall 2008
AccountReader Example
package booklib;
import booklib.BankAccount;
import booklib.JointBankAccount;
import booklib.KeyboardReader;
public class AccountReader
{
private KeyboardReader input =
new KeyboardReader();
public BankAccount readAccount() {...}
}
32
CSD Univ. of Crete Fall 2008
AccountReader Example
public BankAccount readAccount()
{
// declare local vars
// read account type
// read number, balance, owner
if (type == 2)
{
// read joint owner name
return new JointBankAccount(...);
}
else
return new BankAccount(...);
}
it's also aBankAccount
33
CSD Univ. of Crete Fall 2008
AccountReaderTester
import booklib.*;
public class AccountReaderTester
{
public AccountReaderTester()
{
AccountReader accountInput = new
AccountReader();
BankAccount a = accountInput.readAccount();
System.out.println(a);
}
public static void main(String[] args)
{ new AccountReaderTester();
}
}
34
CSD Univ. of Crete Fall 2008
toString is polymorphic
The print statement System.out.println(a);is shorthand for System.out.println(a.toString());
the Java run-time system knows whether a refers to a BankAccount object or to a JointBankAccount object so it calls the correct version of the two toString methods
35
CSD Univ. of Crete Fall 2008
Bank Account Processing
Problem: Read an array of BankAccount objects and process them in several ways.
Reading the array is common to all processors Therefore we start with an abstract account processor class that has
a non-abstract method to do the account reading and provides an abstract method for account processing
Each subclass will provide its own implementation of the processor method.
36
CSD Univ. of Crete Fall 2008
AccountProcessor
abstract public class AccountProcessor
{ private AccountReader inputAccount =
new AccountReader();
protected KeyboardReader console =
new KeyboardReader();
protected BankAccount[] account;
public void readAccounts(){...}
abstract public void processAccounts();
}
semi-colonis necessary
keyword to indicate abstract classes and methods
subclasses willneed to access
them
37
CSD Univ. of Crete Fall 2008
readAccounts Method
public void readAccounts()
{
System.out.println("How many accounts?");
int size = input.readInt();
account = new BankAccount[size];
for (int k = 0; k < account.length; k++)
{
account[k] = inputAccount.readAccount();
}
}
38
CSD Univ. of Crete Fall 2008
MaxBalanceProcessor
public class MaxBalanceProcessor extends AccountProcessor{ public void processAccounts() { double max = account[0].getBalance(); for (int k = 1; k < account.length; k++) { double b = account[k].getBalance(); if (b > max) max = b; } System.out.println{ "The maximum balance is " + max); }}
implement theprocessAccounts
method
39
CSD Univ. of Crete Fall 2008
MaxBalanceProcessorRunner
public class MaxBalanceProcessorRunner{ public static void main(String[] args) { MaxBalanceProcessor program = new MaxBalanceProcessor();
program.readAccounts(); program.processAccounts(); }}
calls method inAccountProcessor
40
CSD Univ. of Crete Fall 2008
A Fund Transfer Method
Problem: Write a method that can be used to transfer a given amount from one bank account to another that works with both BankAccount and JointBankAccount objects:
Without polymorphic types we would need four different methods to cover the four possible types of transfer (bank to bank, joint to joint, bank to joint and joint to bank)
With polymorphism only one method is needed
41
CSD Univ. of Crete Fall 2008
A Fund Transfer Method
public void transfer(BankAccount from,
BankAccount to, double amount;
{
boolean ok = from.withdraw(amount);
if (ok)
{
to.deposit(amount);
}
}
This works because a JointBankAccount "is a" BankAccount
42
CSD Univ. of Crete Fall 2008
Using the Method
BankAccount fred = new BankAccount(...);
BankAccount joan = new BankAccount(...);
JointBankAccount fredMary =
new JointBankAccount(...);
JointBankAccount joanBob =
new JointBankAccount(...);
transfer(fred, joan, 89.55);
transfer(fred, fredMary, 49.35);
transfer(joanBob, fredMary, 100.00);
transfer(joanBob, joan, 50.00);
43
CSD Univ. of Crete Fall 2008
Employee Hierarchy
Employee
Manager
HourlyWorker
PartTimeWorker
CommissionWorker
Everything commonto all employees
These differ onlyin how the salary
is calculated
44
CSD Univ. of Crete Fall 2008
Abstract Employee Class
abstract public class Employee
{
private String name;
public Employee(String name)
{ this.name = name;
}
public String getName()
{ return name;
}
abstract public double grossSalary();
abstract public double netSalary();
}
polymorphicmethods
Constructor forthe name part
45
CSD Univ. of Crete Fall 2008
Subclasses
Manager gross monthly salary,10% deductions.
HourlyWorker gross monthly salary from hours worked and hourly wage, 5%
ideductions. PartTimeWorker
as above with not deductions CommissionWorker
like manager with a commission as a percentage of monthly sales
46
CSD Univ. of Crete Fall 2008
The Manager Class
public class Manager extends Employee
{
protected double gross;
protected double net;
public Manager(String name, double salary)
{
super(name);
gross = salary;
net = 0.9 * gross;
}
public double grossSalary() { return gross; }
public double netSalary() { return net; }
public String toString() {...}
}
call superclassconstructor to
do its part
47
CSD Univ. of Crete Fall 2008
ProcessEmployees
public Employee[] staff;
...
public void doCalculations()
{ totalGrossSalary = totalNetSalary = 0.0;
for (int k = 0; k < staff.length; k++)
{
totalGrossSalry += staff[k].grossSalary();
totalNetSalary += staff[k].netSalary();
System.out.println(staff[k]);
}
totalBenefits =
totalGrossSalary - totalNetSalary
}
a polymorphic loop
48
CSD Univ. of Crete Fall 2008
What is an Adapter Class?
Inheritance always adds functionality. Sometimes we need to subtract functionality. For example we may want to make a class serve a more specific or
simpler purpose by hiding some of its methods. Adapter classes use composition to do this. Our custom format class is an example: hiding the complexity of the
DecimalFormat class.
49
CSD Univ. of Crete Fall 2008
The java.util.Vector class
This is a generic dynamic container class. Some of its constructors and methods are
public Vector()
public Vector(int initialCapacity)
public void addElement(Object obj)
public Object elementAt(int k)
public void setElementAt(int k)
public int size()
// convert vector to an Object array
public Object[] toArray()
// convert to array of specified type
public Object[] toArray(Object[] obj)
50
CSD Univ. of Crete Fall 2008
Vector with BankAccount
Storing BankAccount objects in a Vector containerVector v = new Vector();
v.addElement(new BankAccount(123,"Fred",345.50);
v.addElement(new BankAccount(345,"Mary",435.43);
System.out.println(v.elementAt(0));
System.out.println(v.elementAt(1));
BankAccount b = (BankAccount) v.elementAt(0);
Object amnesiaagain
51
CSD Univ. of Crete Fall 2008
Vector with BankAccount
Converting a Vector to an array
Vector v = new Vector(1000);
...
BankAccount[] a = new BankAccount[v.size()];
a = (BankAccount[]) v.toArray(a);
Object amnesiaagain
52
CSD Univ. of Crete Fall 2008
BankAccountVector Class
package booklib;
import java.util.Vector;
public class BankAccountVector
{
private Vector v; // composition (hide it)
public BankAccountVector() {...}
public BankAccountVector(int initialCap){...}
public void addAccount(BankAccount b) {...}
public BankAccount getAccount(int k) {...}
public void replaceAccount(BankAccount b,
int k) {...}
public int size() {...}
public BankAccount[] toArray() {...}
}
53
CSD Univ. of Crete Fall 2008
BankAccountVector Class
Constructors
public BankAccountVector(){ v = new Vector();}
public BankAccountVector(int initialCap){ v = new Vector(initialCapacity);}
54
CSD Univ. of Crete Fall 2008
BankAccountVector Class
Methods
public void addAccount(BankAccount b){ v.addElement(b);}
public BankAccount getAccount(int k){ return (BankAccount) v.elementAt(k);}
55
CSD Univ. of Crete Fall 2008
BankAccountVector Class
Methods
public void replaceAccount(BankAccount b, int k)
{ v.setElementAt(b,k);
}
public int size()
{ return v.size();
}
public BankAccount[] toArray()
{ BankAccount[] b = new BankAccount[v.size()];
return (BankAccount[]) v.toArray(b);
}
56
CSD Univ. of Crete Fall 2008
A Stack MachineStack Machine is a device that lets you write simple programs that
use a StackStackItems (in our example numbers) are placed on and removed from the
stack using two commands “push” to place on, and “pop” to take offItems are always placed on top of the stack and taken off the top of the
stackA stack is a last-in-first-out structureArithmetic operations can be performed by assuming that the two
operands needed for the operation will be the top two items on the stack
and the answer will be placed back on the stack
A Harder Example
57
CSD Univ. of Crete Fall 2008
A Harder Example
push 5
5
Stack
push 10
5
Stack
10
add
15
Stack
5 + (6 * (5 - 4))
push 5 push 4subtractpush 6multiplypush 5addprint
Any mathematical expression can be converted into a series of machine instructions
58
CSD Univ. of Crete Fall 2008
What are the classes?
Clients view:public static void main(String[] args){ StackMachine sm = new StackMachine(); sm.load(“programFileName”); sm.run();}
ProgramLoaderIts purpose is to read the
program in
void load(String filename)void String getInstruction(int i)int numInstructions()
StackIts purpose is to model
the Stack idea
void push(double value)double pop()
StackMachineCoordinate
all operations
void load(String fileName)void run()
A Harder Example
59
CSD Univ. of Crete Fall 2008
public class StackMachine{ ProgramLoader pl; Stack stack; public StackMachine(){ pl = new ProgramLoader(); stack = new Stack(); } public void load(String fileName){ pl.load(fileName); } public void run(){ String instruction; for(int i=0; i<pl. numInstructions(); i++){ instruction = pl.get(i); System.out.println(instruction); } }
example.stkpush 5 push 4subtractpush 6multiplypush 5addprint
Client codepublic static void main(String[] args){ StackMachine sm = new StackMachine(); sm.load(“example.stk”); sm.run();}
What happens here?
Example… gaining an understanding
60
CSD Univ. of Crete Fall 2008
public class StackMachine{ ... public void run(){ String instruction; for(int i=0; i<pl.numInstructions(); i++){
instruction = pl.get(i); StringTokenizer st = new StringTokenizer(instruction); String command = st.nextToken(); if (command.toUpperCase(“PUSH”){ String parameter = st.nextToken(); stack.push(Double.parseDouble(parameter)); } else if (command.toUpperCase(“PRINT”){ double d = stack.pop(); System.out.println(d); } ...
}}
Messy,
long,
yuck, …
Implementing the instructions: First Solution
61
CSD Univ. of Crete Fall 2008
Think of instruction as “classes” and group them instructions
push
pop
addsubtract
divide
multiply printone parameter
instruction no parameter
instruction
push
pop
add
subtract
dividemultiply
instructionsarithmetic instructions
stack
instructions
utility
instructions
Organized bynumber of parameters
Organized by function
Implementing the instructions: Better Solution
62
CSD Univ. of Crete Fall 2008
InstructionInstruction
OneParameterInstructionOneParameterInstruction NoParameterInstructionNoParameterInstruction
pushpush poppop addadd multiplymultiply dividedivide subtractsubtractprintprint
InstructionInstruction
StackInstructionStackInstruction ArithmeticInstructionArithmeticInstruction UtilityInstructionUtilityInstruction
pushpush poppop add subtract divide multiplyadd subtract divide multiply printprint
Each instruction will know how to “execute” itself Each instruction will know how to initialize itself
Implementing the instructions: Better Solution
63
CSD Univ. of Crete Fall 2008
public class StackMachine{ ... public void run(){ String instruction; for(int i=0; i<pl.numInstructions(); i++){ instruction = pl.get(i);
StringTokenizer st = new StringTokenizer(instruction); String command = st.nextToken(); try{ Instruction instRef =
(Instruction) Class.forName(command)).newInstance(); instRef.load(st); instRef.execute(stack); } catch(Exception e)
System.out.println(“Syntax error – bad instruction”); System.exit(0); }
} }}
Client codepublic static void main(String[] args){ StackMachine sm = new StackMachine(); sm.load(“example.stk”); sm.run();}
Implementing the instructions: Better Solution
64
CSD Univ. of Crete Fall 2008
public interface Instruction{ public void load(StringTokenizer); public void execute(Stack);}
public abstract class ArithmeticInstruction implements Instruction{ public void load(StringTokenizer st){} }
public class Add extends ArithmeticInstruction{ public void execute(Stack stack){ double operand1 = stack.pop(); double operand2 = stack.pop(); stack.push(operand1+operand2); }}
Implementing the instructions: Better Solution
65
CSD Univ. of Crete Fall 2008
public interface Instruction{ public void load(StringTokenizer); public void execute(Stack);}
public abstract class StackInstruction implements Instruction{// only here for design completeness }
public class PopInstruction extends StackInstruction{ public void load(StringTokenizer st){} public void execute(Stack stack){
stack.pop(); }}
public class PushInstruction extends StackInstruction{ double value; public void load(StringTokenizer st){ String parameter = st.nextToken(); value = Double.parseDouble(parameter); } public void execute(Stack stack){ stack.push(value); } }
Implementing the instructions: Better Solution