Applying Inheritance to Solve problems - PowerPoint PPT Presentation

oshin
slide1 l.
Skip this Video
Loading SlideShow in 5 Seconds..
Applying Inheritance to Solve problems PowerPoint Presentation
Download Presentation
Applying Inheritance to Solve problems

play fullscreen
1 / 23
Download Presentation
Applying Inheritance to Solve problems
384 Views
Download Presentation

Applying Inheritance to Solve problems

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

  1. Applying Inheritance to Solve problems Designing with inheritance (c) Eraj Basnayake

  2. 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 allclasses 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

  3. Example Shape 2D Shapes 3D Shapes Circle Rectangle Sphere Cylinder Square Classes: Circle, Rectangle, Sphere, Cylinder, Square, Coordinate Group classes All “Shapes” 2D Shapes Circle Sphere Coordinate Rectangle Cylinder Square 3D Shapes Square is a Rectangle Inheritance hierarchy Designing with inheritance (c) Eraj Basnayake

  4. Example… Shape Shapes2D Shapes3D Circle Rectangle Sphere Cylinder Square Distribute Responsibilities: Shape +getSurfaceArea() +clone() +equals() +toString() +Object getLocation() Shape3D +getVolume() Shape2D + ? Is Shape2D needed? Designing with inheritance (c) Eraj Basnayake

  5. Example … Abstract classes. public abstract class Shape{ public abstractdouble getSurfaceArea(); public abstractObject getLocation(); public abstractObject clone(); public abstractString toString(); public abstractboolean 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

  6. 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

  7. Interfaces vs Abstract classes, how to decide? Not all programming languages have Interface’s! 1 unimplemented method 2 unimplemented method All methods unimplemented All methods implemented … Abstract class Interface Regular Class 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

  8. 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

  9. Its all still inheritance! extends public interface Shape implements Clonable{ … } public abstract class Shape2D implements Shape{ … } public class Circle extends Shape2D{ } Client Code … Circle c = new Circle(); … Shape s = c; Cloneable cln = s; Shape2D s2d = (Shape2D)s; • Circle has to implement all • unimplemented methods of • 2DShape • Shape • Clonable Designing with inheritance (c) Eraj Basnayake

  10. 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 CircleAND 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

  11. 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

  12. 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 add push 10 10 15 5 5 Stack Stack Stack Any mathematical expression can be converted into a series of machine instructions. push 5 push 4 subtract push 6 multiply push 5 add print 5 + (6 * (5 - 4)) Designing with inheritance (c) Eraj Basnayake

  13. Example… Stack Its purpose is to model the Stack idea. void push(double value) double pop() ProgramLoader Its purpose is to read the program in. void load(String filename) void String getInstruction(int i) int numInstructions() 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() Designing with inheritance (c) Eraj Basnayake

  14. Example… gaining an understanding example.stk push 5 push 4 subtract push 6 multiply push 5 add print 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); } } 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

  15. Example… implementing the instructions - one solution 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, … Designing with inheritance (c) Eraj Basnayake

  16. Example… another way Think of instruction as “classes” and group them instructions Organized by number of parameters pop divide add push subtract print multiply one parameter instruction no parameter instruction Organized by function arithmetic instructions instructions multiply stack instructions divide add push subtract pop print utility instructions Designing with inheritance (c) Eraj Basnayake

  17. Example… another way Instruction OneParameterInstruction OneParameterInstruction push print pop add multiply divide subtract Instruction ArithmeticInstruction UtilityInstruction StackInstruction push pop add subtract divide multiply print • Each instruction will know how to “execute” itself • Each instruction will know how to initialize itself. Designing with inheritance (c) Eraj Basnayake

  18. 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){} } Quick Review What’s going on? … Add a = new Add(); Instruction i = a; i.load(st); i.execute(stack); 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

  19. 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

  20. Example… another way 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().equals(“PUSH”)){ Push p = new Push(); p.load(st); p.execute(stack); }else if (command.toUpperCase().equals(“SUBTRACT”)){ Subtract p = new Subtract(); p.load(st); p.execute(stack); } … } } } 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().equals(“PUSH”)){ Push p = new Push(); p.load(st); p.execute(stack); }else if (command.toUpperCase().equals(“SUBTRACT”)){ Subtract p = new Subtract(); p.load(st); p.execute(stack); } … } } } 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().equals(“PUSH”)){ Push p = new Push(); p.load(st); p.execute(stack); }else if (command.toUpperCase().equals(“SUBTRACT”)){ Subtract p = new Subtract(); p.load(st); p.execute(stack); } … } } } Will this work? Is it any better? common code! Designing with inheritance (c) Eraj Basnayake

  21. Example… another way Will this work? 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().equals(“PUSH”)){ Push p = new Push(); }else if (command.toUpperCase().equals(“SUBTRACT”)){ Subtract p = new Subtract(); }else if … … p.load(st); p.execute(stack); }//for } } Common code factored out. Will this work? Why or why not? Designing with inheritance (c) Eraj Basnayake

  22. Example… another way Will this work? 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(); Instruction p; if (command.toUpperCase().equals(“PUSH”)){ p = new Push();//upcast }else if (command.toUpperCase().equals(“SUBTRACT”)){ p = new Subtract();//upcast } … p.load(st);//method overriding p.execute(stack); //method overriding }//for } } Designing with inheritance (c) Eraj Basnayake

  23. Example… another way 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); } } } } A really cool way to do all that! Client code public static void main(String[] args){ StackMachine sm = new StackMachine(); sm.load(“example.stk”); sm.run(); } Designing with inheritance (c) Eraj Basnayake