Transcript Document 7841666
Applying Inheritance to Solve problems
Designing with inheritance (c) Eraj Basnayake 1
Applied Inheritance
•
Decide on the classes involved from the problem description
•
Group classes into
conceptually equivalent
groups
•
Per 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 location. The shapes that need to be modeled are: Circle, Rectangle, Sphere, Cylinder, and a Square.
What classes will you need? Draw an UML diagram showing class relationships if any.
Designing with inheritance (c) Eraj Basnayake 2
Example
Classes: Circle, Rectangle, Sphere, Cylinder, Square, Coordinate Group classes
All “Shapes”
2D Shapes Circle Rectangle Sphere Cylinder Coordinate Square 3D Shapes Square is a Rectangle Inheritance hierarchy Shape Circle 2D Shapes Rectangle 3D Shapes Cylinder Sphere Square
Designing with inheritance (c) Eraj Basnayake 3
Example…
Shape Circle Shapes2D Rectangle Shapes3D Cylinder Sphere Square Distribute Responsibilities: Shape +getSurfaceArea() +clone() +equals() +toString() +Object getLocation() Shape2D + ?
Shape3D +getVolume() Is Shape2D needed?
Designing with inheritance (c) Eraj Basnayake 4
Example … Abstract classes.
public
abstract
class Shape{ public
abstract
double getSurfaceArea(); public
abstract
Object getLocation(); public
abstract
Object clone(); public
abstract
String toString(); public
abstract
boolean equals(); Observe the syntax of Shape.
The methods are not empty methods }
Abstract Class:
A class with
at least one
unimplemented method.
Shape above is an example of an Abstract class.
Interface:
A class with
only
unimplemented methods.
} public
interface
Shape{ public double getSurfaceArea(); public Object getLocation(); public Object clone(); public String toString(); public boolean equals();
Designing with inheritance (c) Eraj Basnayake 5
Abstract Classes
• • • • • An
abstract class
is a
placeholder
– It is too generic to be of use by itself. – It is used in a class hierarchy to organize common features at appropriate levels.
Abstract class
cannot be instantiated
– However an abstract class variable can reference any concrete derived object.
An
abstract method
has no implementation, just a signature
– It is never intended to be called directly (a
placeholder
).
– Abstract methods can appear only in classes that themselves been declared abstract
The modifier
abstract
–
is used to define abstract classes & methods
The children of the abstract class are expected to define implementations for the abstract methods in ways appropriate for them
If a child class does not define all abstract methods of the parent, then the child is also abstract!
Designing with inheritance (c) Eraj Basnayake 6
Interfaces vs Abstract classes, how to decide?
Not all programming languages have Interface’s!
… Regular Class Abstract class Interface So why have abstract classes and interfaces?
•
To enforce design conformity.
•
Clients can expect a uniform set of methods for related classes.
•
Interface’s are used to “tag” a class with a property. While interfaces
are classes
, they represent “action ideas”, “verbs” or “properties” about class.
Designing with inheritance (c) Eraj Basnayake 7
Interfaces...
Sample Interface’s: Cloneable, Drawable, Colorable, Runable, Comparable, … Q: How do you inherit from an interface?
A: By
implement
’ing the interface.
extends
public interface Shape
implements
Cloneable{ … } } public abstract class Shape2D
implements
Shape{ … Q: How do you inherit from an Abstract class?
A: The usual way, by
extend
’ing
} public class Circle
extends
Shape2D{ …
Designing with inheritance (c) Eraj Basnayake 8
Its all still inheritance!
public
interface extends
Shape
implements
Clonable{ … } } public
abstract
class Shape2D
implements
Shape{ … } public
class
Circle
extends
Shape2D{ Circle
has to
unimplemented methods of
•
2DShape
•
Shape
•
Clonable implement
all
Client Code … Circle c = new Circle(); … Shape s = c; Cloneable cln = s; Shape2D s2d = (Shape2D)s;
Designing with inheritance (c) Eraj Basnayake 9
Its all still inheritance!
Client Code … Circle c = new Circle(); … Shape s = c; Cloneable cln = s; Shape2D s2d = (Shape2D) s; through c you can access ALL methods of Circle AND its parents!
Through s you can access ONLY methods of Shape and Cloneable implemented in Circle Through cln you can access ONLY methods of Cloneable implemented in Circle Through s2d you can access ONLY methods of Shape, Cloneable, and Shape2D implemented in Circle.
Designing with inheritance (c) Eraj Basnayake 10
Multiple Inheritance
Some programming languages allow for multiple inheritance.
In Java: Can have multiple interface implementation .
Single inheritance. Types of possible inheritance:
•
An interface can inherit from multiple interfaces by implementing
•
A class (abstract or otherwise) can inherit from multiple interfaces by implementing
•
A class (abstract or otherwise) can inherit from a single other (abstract or normal) class.
Designing with inheritance (c) Eraj Basnayake 11
A harder Example
A Stack Machine is a device that lets you write simple programs that use a Stack. Items (in our example numbers) are placed on and removed from the stack using two commands “push” to place on, and “pop” to take off.
Items are always placed on top of the stack and taken off the top of the stack.
A stack is a last-in-first-out structure. Arithmetic 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.
push 5 push 10 add 10 5 5 15 Stack Stack Stack Any mathematical expression can be converted into a series of machine instructions.
push 5 push 4 5 + (6 * (5 - 4)) subtract push 6 multiply push 5 add
Designing with inheritance (c) Eraj Basnayake
12
Example…
What are the classes?
Clients view: public static void main(String[] args){ StackMachine sm = new StackMachine(); sm.load(“programFileName”); sm.run(); } StackMachine
Coordinate all operations.
void load(String fileName) void run() ProgramLoader
Its purpose is to read the program in.
void load(String filename) void String getInstruction(int i) int numInstructions()
Designing with inheritance (c) Eraj Basnayake
Stack
Its purpose is to model the Stack idea.
void push(double value) double pop()
13
Example… gaining an understanding
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
push 5 push 4 subtract push 6 multiply push 5 add print Client code public static void main(String[] args){ StackMachine sm = new StackMachine(); sm.load(“example.stk”); sm.run(); }
What happens here?
Designing with inheritance (c) Eraj Basnayake 14
Example… implementing the instructions - one solution
public class StackMachine{ … public void run(){ String instruction; for(int i=0; i
Designing with inheritance (c) Eraj Basnayake
Messy, long, yuck, …
15
Example… another way
Think of instruction as “classes” and group them Organized by number of parameters push pop divide add subtract multiply print one parameter instruction Organized by function instructions no parameter instruction stack arithmetic instructions instructions instructions push multiply add divide subtract pop print
Designing with inheritance (c) Eraj Basnayake
utility instructions
16
Example… another way
OneParameterInstruction Instruction OneParameterInstruction push print pop add multiply divide subtract StackInstruction push pop Instruction ArithmeticInstruction add subtract divide multiply UtilityInstruction print
• •
Each instruction will know how to “execute” itself Each instruction will know how to initialize itself.
Designing with inheritance (c) Eraj Basnayake 17
Example… another way
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); } }
Designing with inheritance (c) Eraj Basnayake
Quick Review What’s going on?
… Add a = new Add(); Instruction i = a; i.load(st); i.execute(stack);
18
Example… another way
public interface Instruction{ public void load(StringTokenizer); public void execute(Stack); } public abstract class StackInstruction implements Instruction{ //only here for design completeness } public class Pop extends StackInstruction{ public void load(StringTokenizer st){} public void execute(Stack stack){ stack.pop(); } } public class Push 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); } }
Designing with inheritance (c) Eraj Basnayake 19
Example… another way
Will this work?
Is it any better?
Designing with inheritance (c) Eraj Basnayake
common code!
20
Example… another way
Will this work?
public class StackMachine{ … public void run(){ String instruction; for(int i=0; i
Push p = new Push();
}else if (command.toUpperCase().equals(“SUBTRACT”)){
Subtract p = new Subtract();
}else if … …
p.load(st); p.execute(stack);
Common code factored out.
} }
Designing with inheritance (c) Eraj Basnayake
Will this work?
Why or why not?
21
Example… another way
Will this work?
public class StackMachine{ … public void run(){ String instruction; for(int i=0; i
Instruction p;
if (command.toUpperCase().equals(“PUSH”)){
p = new Push();
//upcast }else if (command.toUpperCase().equals(“SUBTRACT”)){ } …
p = new Subtract();
//upcast
p.load(st); p.execute(stack);
//method overriding //method overriding }//for } }
Designing with inheritance (c) Eraj Basnayake 22
Example… another way
public class StackMachine{ … public void run(){ String instruction; for(int i=0; i
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 code } public static void main(String[] args){ StackMachine sm = new StackMachine(); sm.load(“example.stk”); sm.run(); }
Designing with inheritance (c) Eraj Basnayake 23