# Double Dispatch with a 3 by 3 matrix class Rock def fight other other.fightWithRock self end def fightWithRock other "Tie" end def fightWithPaper other "Paper wins" end def fightWithScissors other "Rock wins" end end class Paper def fight other other.fightWithPaper self end def fightWithRock other "Paper wins" end def fightWithPaper other "Tie" end def fightWithScissors other "Scissors wins" end end class Scissors def fight other other.fightWithScissors self end def fightWithRock other "Rock wins" end def fightWithPaper other "Scissors wins" end def fightWithScissors other "Tie" end end Rock.new.fight(Scissors.new) # Exercise: Which cell is being filled in the table with the following calls? Recall: # [Class 1] # R P S # R | | | | #[Class 2] P | | | | # S | | | | # # Assume "Class 1" is "self" (object you're sending a message to) and "Class 2" is the parameter) # print Rock.new.fight(Scissors.new) --> X # print Scissors.new.fight(Rock.new) --> Y # print Paper.new.fight(Paper.new) --> Z # How would we evaluate this if we were an interpreter? # Simple Double Dispatch example class A def f x x.fWithA self end def fWithA a "(a, a) case" end def fWithB b "(b, a) case" end end class B def f x x.fWithB self end def fWithA a "(a, b) case" end def fWithB b "(b, b) case" end end # print A.new.f(A.new) + " " # print A.new.f(B.new) + " " # print B.new.f(A.new) + " " # print B.new.f(B.new) + "\n" # Visitor version! class RockV def accept(visitor) visitor.visitRock(self) end def visitRock(rock) "Tie" end def visitScissors(scissors) "Rock Wins" end def visitPaper(paper) "Paper Wins" end end class PaperV def accept(visitor) visitor.visitPaper(self) end def visitRock(rock) "Tie" end def visitScissors(scissors) "Scissors Wins" end def visitPaper(paper) "Paper Wins" end end class ScissorsV def accept(visitor) visitor.visitScissors(self) end def visitRock(rock) "Rock Wins" end def visitScissors(scissors) "Tie" end def visitPaper(paper) "Scissors Wins" end end class Stringer def visitRock(rock) "Print -> Rock" end def visitScissors(scissors) "Print -> Scissors" end def visitPaper(paper) "Print -> Paper" end end