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

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

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

Page 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)

Where Were We?Where Were We?

• Attempting to spray ants with ant poison and Attempting to spray ants with ant poison and (generic) insects with generic spray(generic) insects with generic spray

• If there is not a complete match between the If there is not a complete match between the signatures of methods in base and derived signatures of methods in base and derived classes there is no polymorphismclasses there is no polymorphism

• Compiler determines the call by using the Compiler determines the call by using the declared typedeclared type

• Now apply thisNow apply this

Page 2: 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)

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”); }};

Page 3: 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)

RemarksRemarks

• It appears that we are attempting to use It appears that we are attempting to use polymorphism polymorphism bothboth on the on the PoisonPoison type type andand the the InsectInsect type type

• The only polymorphism that will work is with The only polymorphism that will work is with a static reference to a static reference to PoisonPoison (and a run-time (and a run-time reference to either reference to either PoisonPoison or or AntPoisonAntPoison) ) and a static reference to and a static reference to AntAnt. Period. Period

Page 4: 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)

Test ThisTest This

Poison container = new AntPoison();Poison container = new AntPoison();

Insect bugType = new Ant();Insect bugType = new Ant();

container.spray(bugType);container.spray(bugType);

bugType = new Insect();bugType = new Insect();

container.spray(bugType);container.spray(bugType);

ProducesProduces

Generic SprayGeneric Spray

Generic SprayGeneric Spray

Page 5: 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)

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”); }};

Page 6: 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)

Why?Why?

Because there is no Because there is no sprayspray method in method in AntAnt with an insect parameterwith an insect parameter

But, callingBut, callingPoison container = new AntPoison();Poison container = new AntPoison();

Container.spray(new Ant());Container.spray(new Ant());

Container.spray(new Container.spray(new Insect());Insect());

Page 7: 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)

ResultsResults

• ProducesProduces

Spraying ant with ant spraySpraying ant with ant spray

Generic sprayGeneric spray Which at least works on ants.Which at least works on ants. Doesn’t work properly on insectsDoesn’t work properly on insects

Page 8: 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)

Use Polymorphism ProperlyUse Polymorphism Properly

Can’t use 2 different container references Can’t use 2 different container references and 2 different parameter references at one and 2 different parameter references at one timetime

Do it in two stepsDo it in two steps Bounce from the Bounce from the PoisonPoison class to the Insect class to the Insect

class using class using beingSprayed() beingSprayed() methods in all methods in all classesclasses

Make use of Make use of thisthis, because it is , because it is staticallystatically determineddetermined

Page 9: 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)

Fix up InsectFix up Insect

public class Poison{public class Poison{

public void spray (Insect aBug){public void spray (Insect aBug){

System.out.println(“GenericSystem.out.println(“Generic

Spray”);Spray”);

aBug.beingSprayed(this); }aBug.beingSprayed(this); }

}}

public class AntPoison{…} //no public class AntPoison{…} //no

//being Sprayed//being Sprayed

Page 10: 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)

Put in the Bounce CallPut in the Bounce Call

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

Page 11: 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)

NoteNote

Because we used Because we used thisthis, the actual , the actual parameter of parameter of beingSprayedbeingSprayed is always of is always of type type PoisonPoison

Insect Insect is now working correctlyis now working correctly

Page 12: 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)

TestTest

Poison container = new AntPoison();Poison container = new AntPoison();Insect aBug = new Ant();Insect aBug = new Ant();container.spray(aBug);container.spray(aBug);aBug = new Insect();aBug = new Insect();container.spray(aBug);container.spray(aBug);

ProducesProducesGeneric SprayGeneric SprayAnt being sprayed with poisonAnt being sprayed with poisonGeneric SprayGeneric SprayInsect being sprayed with poisonInsect being sprayed with poison

Page 13: 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)

ProblemProblem

• We are only spraying with generic poisonWe are only spraying with generic poison• In order to make use of a In order to make use of a spray spray method in method in

the AntPoison class we must repeat the the AntPoison class we must repeat the spray() spray() method with exactly the same method with exactly the same signature in the signature in the AntPoisonAntPoison derived class derived class

• Furthermore, we need a Furthermore, we need a beingSprayed() beingSprayed() method of each poison type in both method of each poison type in both InsectInsect and and AntAnt

Page 14: 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)

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

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

Page 15: 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)

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”); }};

Page 16: 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)

RemarksRemarks

To insure polymorphism after the bounce To insure polymorphism after the bounce Insect Insect and and AntAnt must have 2 must have 2 beingSprayed()beingSprayed() methods with methods with differentdifferent signatures (i.e. parameters)signatures (i.e. parameters)

To have the ability to use ant poison the To have the ability to use ant poison the spray() spray() method is repeated method is repeated with the with the same signaturesame signature in both Insect and in both Insect and AntAnt

Page 17: 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)

Let’s Test ThisLet’s Test This

Poison container = new AntPoison();Poison container = new AntPoison();

Insect aBug = new Ant();Insect aBug = new Ant();

container.spray(aBug);container.spray(aBug);

aBug = new Insect();aBug = new Insect();

container.spray(aBug);container.spray(aBug);

Poison container = new Poison();Poison container = new Poison();

Insect aBug = new Ant();Insect aBug = new Ant();

container.spray(aBug);container.spray(aBug);

aBug = new Insect();aBug = new Insect();

container.spray(aBug);container.spray(aBug);

Page 18: 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)

Hooray!Hooray!

Ant sprayed with ant poisonAnt sprayed with ant poison

Insect sprayed with ant poisonInsect sprayed with ant poison

Ant sprayed with generic poisonAnt sprayed with generic poison

Insect sprayed with generic poisonInsect sprayed with generic poison

Page 19: 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)

What we HaveWhat we Have

Poison

Spray(Insect)

AntPoison

Spray(Insect)

Insect

Ant

beingSprayed(Poison)

beingSprayed(Poison)

beingSprayed(AntPoison)

beingSprayed(AntPoison)

•Methods in Poison and AntPoison are identical!!

•Note output in Insect classes--Insect shouldn’t know anything about Poison

Page 20: 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)

One Way OutOne Way Out

• Let the Let the beingSprayedbeingSprayed methods call other methods call other methods inthe Poison classesmethods inthe Poison classes• Call them Call them sprayIt()sprayIt()• Param types are with Param types are with InsectInsect and and AntAnt

• Put the print statements into the Put the print statements into the PoisonPoison (Visitor) classes(Visitor) classes

Page 21: 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)

We ObtainWe ObtainInsect

Ant

Poison

AntPoison

beingSprayed(Poison)

beingSprayed(Poison)

Spray(Insect)

SprayIt(Insect)

SprayIt(Insect)SprayIt(Ant)

SprayIt(Ant)

print statements

Object Structure Visitor

Page 22: 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)

Now SimplifyNow Simplify

• The above is the general solution to double The above is the general solution to double dispatchdispatch

• It is too general for our purposesIt is too general for our purposes• Make Make InsectInsect and and PoisonPoison abstract abstract• Begin with the Object Structure and eliminate Begin with the Object Structure and eliminate Spray()Spray() from from PoisonPoison

• SprayIt(Insect)SprayIt(Insect) is never called, so is never called, so eliminateeliminate

• We obtainWe obtain

Page 23: 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)

beingSprayed(Poison)

beingSprayed(Poison)

Insect

Ant

Poison

Ant

SprayIt(Ant)

SprayIt(Ant)

Visitor Object Structure Poison.sprayIt(this)

Page 24: 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)

Now Add the RoachesNow Add the Roaches

• Call Call beingSprayed() sprayAnt(),beingSprayed() sprayAnt(), because Insect is abstractbecause Insect is abstract

• You will need 2 methods, You will need 2 methods, sprayAnt(Ant)sprayAnt(Ant) as well as as well as sprayRoach(Roach)sprayRoach(Roach) in in PoisonPoison

• Note the excess baggage, e.g. spraying a Note the excess baggage, e.g. spraying a roach with ant poisonroach with ant poison

Page 25: 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)

The Visitor PatternThe Visitor Pattern

Is a GoF PatternIs a GoF Pattern Purpose:Purpose: To implement operations on the To implement operations on the

objects of a structure without keeping those objects of a structure without keeping those operations in the object themselvesoperations in the object themselves

Key IdeaKey Idea: The operations that are executed : The operations that are executed depend on both the type of the operation and depend on both the type of the operation and the type of the node to which it is appliedthe type of the node to which it is applied

Advantage:Advantage: Extension is dead easy Extension is dead easy DisadvantageDisadvantage: Methods grow like weeds: Methods grow like weeds

Page 26: 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)

In Our CaseIn Our Case

InsectInsect is the object structureis the object structure PoisonPoison is the visitor is the visitor Note the duplication in code—dangerous!Note the duplication in code—dangerous! The The InsectInsect classes have to know about classes have to know about

the the PoisonPoison classes classes There is a better way!There is a better way!

Do a double bounceDo a double bounce

Page 27: 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)

Structure of the VisitorStructure of the Visitor

Poison sprayAnt(Ant);sprayRoach(Roach);

AntPoisonsprayAnt(Ant);sprayRoach(Roach);

RoachPoisonsprayAnt(Ant);sprayRoach(Roach);

Page 28: 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)

The Visitor PatternThe Visitor Pattern

• Main idea: use an Main idea: use an iteratoriterator or or traversaltraversal to visit to visit each node of the object structure and visit it with each node of the object structure and visit it with the corresponding node of the visitor structurethe corresponding node of the visitor structure

• The object structure classes have no knowledge of The object structure classes have no knowledge of the visitor classesthe visitor classes

• What gets carried out depends on two thingsWhat gets carried out depends on two things• The type of the visitorThe type of the visitor• The type of the object nodeThe type of the object node

• Hence double dispatchHence double dispatch

Page 29: 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)

Object Structure VisitedObject Structure Visited

InsectgetSprayed(Poison);

AntgetSprayed(Poison p)

RoachgetSprayed(Poison p)

p.sprayAnt(this); p.sprayRoach(this);

Page 30: 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)

Structure of the Visitor PatternStructure of the Visitor Pattern

VisitConcreteElementA(ConcreteElementA)

VisitConcreteElementB(ConcreteElementB)

VisitConcreteElementA(ConcreteElementA)

VisitConcreteElementB(ConcreteElementB)

Visitor

ConcreteVisitor1

VisitConcreteElementB(ConcreteElementB)

VisitConcreteElementA(ConcreteElementA)

ConcreteVisitor2

The Visitor

Page 31: 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)

Object StructureObject Structure

Accept(Visitor)

Element

ConcreteElementA

Accept(Visitor v)

OperationA()

ConcreteElementA

Accept(Visitor v)

OperationB()

v->VisitConcreteElementB(this)

v->VisitConcreteElementA(this)

ObjectStructure