Presentation is loading. Please wait.

Presentation is loading. Please wait.

Where Were We? Attempting to spray ants with ant poison and (generic) insects with generic spray Attempting to spray ants with ant poison and (generic)

Similar presentations


Presentation on theme: "Where Were We? Attempting to spray ants with ant poison and (generic) insects with generic spray Attempting to spray ants with ant poison and (generic)"— Presentation transcript:

1 Where Were We? Attempting to spray ants with ant poison and (generic) insects with generic spray Attempting to spray ants with ant poison and (generic) insects with generic spray If there is not a complete match between the signatures of methods in base and derived classes there is no polymorphism If there is not a complete match between the signatures of methods in base and derived classes there is no polymorphism Compiler determines the call by using the declared type Compiler determines the call by using the declared type Now apply this Now apply this

2 public class Poison{ public void spray(Insect aBug){ System.out.println(“Generic Spray”); } public void spray(Ant antBug){ System.out.println(“Generic Ant Spray”); } }; public class AntPoison extends Poison{ public void spray(Ant antBug){ System.out.println(“Spraying Ant with Ant spray”); } };

3 Remarks It appears that we are attempting to use polymorphism both on the Poison type and the Insect type It appears that we are attempting to use polymorphism both on the Poison type and the Insect type The only polymorphism that will work is with a static reference to Poison (and a run-time reference to either Poison or AntPoison ) and a static reference to Ant. Period The only polymorphism that will work is with a static reference to Poison (and a run-time reference to either Poison or AntPoison ) and a static reference to Ant. Period

4 Test This Poison container = new AntPoison(); Insect bugType = new Ant(); container.spray(bugType); bugType = new Insect(); container.spray(bugType);Produces Generic Spray

5 public class Poison{ public void spray(Insect aBug){ System.out.println(“Generic Spray”); } public void spray(Ant antBug){ System.out.println(“Generic Ant Spray”); } }; public class AntPoison extends Poison{ public void spray(Ant antBug){ System.out.println(“Spraying Ant with Ant spray”); } };

6 Why?  Because there is no spray method in Ant with an insect parameter  But, calling Poison container = new AntPoison(); Container.spray(new Ant()); Container.spray(new Insect());

7 Results Produces Produces Spraying ant with ant spray Generic spray  Which at least works on ants.  Doesn’t work properly on insects

8 Use Polymorphism Properly  Can’t use 2 different container references and 2 different parameter references at one time  Do it in two steps  Bounce from the Poison class to the Insect class using beingSprayed() methods in all classes  Make use of this, because it is statically determined

9 Fix up Insect public class Poison{ public void spray (Insect aBug){ public void spray (Insect aBug){ System.out.println(“Generic System.out.println(“Generic Spray”); Spray”); aBug.beingSprayed(this); } aBug.beingSprayed(this); }} public class AntPoison{…} //no //being Sprayed //being Sprayed

10 Put in the Bounce Call public class Insect{ public void beingSprayed(Poison public void beingSprayed(Poison aPoison){ aPoison){ System.out.println(“Insect sprayed System.out.println(“Insect sprayed with poison”);} with poison”);} Public class Ant extends Insect{ public void beingSprayed(Poison public void beingSprayed(Poison aPoison){ aPoison){ System.out.println(“Ant sprayed System.out.println(“Ant sprayed with poison”); with poison”);}}

11 Note  Because we used this, the actual parameter of beingSprayed is always of type Poison  Insect is now working correctly

12 Test Poison container = new AntPoison(); Insect aBug = new Ant(); container.spray(aBug); aBug = new Insect(); container.spray(aBug);Produces Generic Spray Ant being sprayed with poison Generic Spray Insect being sprayed with poison

13 Problem We are only spraying with generic poison We are only spraying with generic poison In order to make use of a spray method in the AntPoison class we must repeat the spray() method with exactly the same signature in the AntPoison derived class In order to make use of a spray method in the AntPoison class we must repeat the spray() method with exactly the same signature in the AntPoison derived class Furthermore, we need a beingSprayed() method of each poison type in both Insect and Ant Furthermore, we need a beingSprayed() method of each poison type in both Insect and Ant

14 public class Poison{ public void spray(Insect aBug){ aBug.beingSprayed(this); } } ; public class AntPoison extends Poison{ public void spray(Insect aBug){ aBug.beingSprayed(this); } };

15 public class Insect{ public void beingSprayed(Poison aPoison){ System.out.println( “ Insect sprayed with generic poison ” ); } public void beingSprayed(AntPoison aPoison){ System.out.println( “ Insect sprayed with ant poison ” ); } }; Public class Ant extends Insect{ public void beingSprayed(Poison aPoison){ System.out.println( “ Ant sprayed with generic poison ” ); } public void beingSprayed(AntPoison aPoison){ System.out.println( “ Ant sprayed with ant poison ” ); } };

16 Remarks  To insure polymorphism after the bounce Insect and Ant must have 2 beingSprayed() methods with different signatures (i.e. parameters)  To have the ability to use ant poison the spray() method is repeated with the same signature in both Insect and Ant

17 Let’s Test This Poison container = new AntPoison(); Insect aBug = new Ant(); container.spray(aBug); aBug = new Insect(); container.spray(aBug); Poison container = new Poison(); Insect aBug = new Ant(); container.spray(aBug); aBug = new Insect(); container.spray(aBug);

18 Hooray! Ant sprayed with ant poison Insect sprayed with ant poison Ant sprayed with generic poison Insect sprayed with generic poison

19 What we Have Poison Spray(Insect) AntPoison Spray(Insect) Insect Ant beingSprayed(Poison) beingSprayed(AntPoison) Methods in Poison and AntPoison are identical!! Note output in Insect classes-- Insect shouldn’t know anything about Poison

20 One Way Out Let the beingSprayed methods call other methods inthe Poison classes Let the beingSprayed methods call other methods inthe Poison classes Call them sprayIt() Call them sprayIt() Param types are with Insect and Ant Param types are with Insect and Ant Put the print statements into the Poison (Visitor) classes Put the print statements into the Poison (Visitor) classes

21 We Obtain Insect Ant Poison AntPoison beingSprayed(Poison) Spray(Insect) SprayIt(Insect) SprayIt(Ant) print statements Object Structure Visitor

22 Now Simplify The above is the general solution to double dispatch The above is the general solution to double dispatch It is too general for our purposes It is too general for our purposes Make Insect and Poison abstract Make Insect and Poison abstract Begin with the Object Structure and eliminate Spray() from Poison Begin with the Object Structure and eliminate Spray() from Poison SprayIt(Insect) is never called, so eliminate SprayIt(Insect) is never called, so eliminate We obtain We obtain

23 beingSprayed(Poison) Insect Ant Poison Ant SprayIt(Ant) VisitorObject StructurePoison.sprayIt(this)

24 Now Add the Roaches Call beingSprayed() sprayAnt(), because Insect is abstract Call beingSprayed() sprayAnt(), because Insect is abstract You will need 2 methods, sprayAnt(Ant) as well as sprayRoach(Roach) in Poison You will need 2 methods, sprayAnt(Ant) as well as sprayRoach(Roach) in Poison Note the excess baggage, e.g. spraying a roach with ant poison Note the excess baggage, e.g. spraying a roach with ant poison

25 The Visitor Pattern  Is a GoF Pattern  Purpose: To implement operations on the objects of a structure without keeping those operations in the object themselves  Key Idea: The operations that are executed depend on both the type of the operation and the type of the node to which it is applied  Advantage: Extension is dead easy  Disadvantage: Methods grow like weeds

26 In Our Case  Insect is the object structure  Poison is the visitor  Note the duplication in code—dangerous!  The Insect classes have to know about the Poison classes  There is a better way!  Do a double bounce

27 Structure of the Visitor Poison sprayAnt(Ant); sprayRoach(Roach); AntPoison sprayAnt(Ant); sprayRoach(Roach); RoachPoison sprayAnt(Ant); sprayRoach(Roach);

28 The Visitor Pattern Main idea: use an iterator or traversal to visit each node of the object structure and visit it with the corresponding node of the visitor structure Main idea: use an iterator or traversal to visit each node of the object structure and visit it with the corresponding node of the visitor structure The object structure classes have no knowledge of the visitor classes The object structure classes have no knowledge of the visitor classes What gets carried out depends on two things What gets carried out depends on two things The type of the visitor The type of the visitor The type of the object node The type of the object node Hence double dispatch Hence double dispatch

29 Object Structure Visited Insect getSprayed(Poison); Ant getSprayed(Poison p) Roach getSprayed(Poison p) p.sprayAnt(this);p.sprayRoach(this);

30 Structure of the Visitor Pattern VisitConcreteElementA(ConcreteElementA) VisitConcreteElementB(ConcreteElementB) VisitConcreteElementA(ConcreteElementA) VisitConcreteElementB(ConcreteElementB) Visitor ConcreteVisitor1 VisitConcreteElementB(ConcreteElementB) VisitConcreteElementA(ConcreteElementA) ConcreteVisitor2 The Visitor

31 Object Structure Accept(Visitor) Element ConcreteElementA Accept(Visitor v) OperationA() ConcreteElementA Accept(Visitor v) OperationB() v->VisitConcreteElementB(this) v->VisitConcreteElementA(this) ObjectStructure


Download ppt "Where Were We? Attempting to spray ants with ant poison and (generic) insects with generic spray Attempting to spray ants with ant poison and (generic)"

Similar presentations


Ads by Google