DispatchTest.java (5506B)
1 // Copyright (c) 2009, 2015 Tomas Hlavaty All rights reserved. 2 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions 5 // are met: 6 7 // Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following 9 // disclaimer. Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following 11 // disclaimer in the documentation and/or other materials provided 12 // with the distribution. 13 14 // Neither the name of jmultimethod nor the names of its contributors 15 // may be used to endorse or promote products derived from this 16 // software without specific prior written permission. 17 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 29 // OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 // FLAW: Java reasons about types of variables instead of values 32 33 // for asteroid example see wikipedia visitor pattern 34 35 package jmultimethod; 36 37 public class DispatchTest { 38 static class Asteroid { 39 String id; 40 public Asteroid(String id) {this.id = id;} 41 public String id() {return id;} 42 } 43 static class Spaceship { 44 String name; 45 public Spaceship(String name) {this.name = name;} 46 public String name() {return name;} 47 } 48 static class Static { 49 static void colide(Asteroid x, Asteroid y) { 50 System.out.println("AA colide " + x.id() + " with " + y.id()); 51 } 52 static void colide(Asteroid x, Spaceship y) { 53 System.out.println("AS colide " + x.id() + " with " + y.name()); 54 } 55 static void colide(Spaceship x, Asteroid y) { 56 System.out.println("SA colide " + x.name() + " with " + y.id()); 57 } 58 static void colide(Spaceship x, Spaceship y) { 59 System.out.println("SS colide " + x.name() + " with " + y.name()); 60 } 61 static void colide(Object x, Object y) { 62 System.out.println("OO colide " + x + " with " + y); 63 } 64 static void run() { 65 run1(); 66 run2(); 67 } 68 static void run1() { 69 System.out.println("Static: explicitly typed"); 70 Asteroid a1 = new Asteroid("A1"); 71 Asteroid a2 = new Asteroid("A2"); 72 Spaceship s1 = new Spaceship("S1"); 73 Spaceship s2 = new Spaceship("S2"); 74 colide(a1, a2); 75 colide(a1, s1); 76 colide(s1, a1); 77 colide(s1, s2); 78 } 79 static void run2() { 80 System.out.println("Static: superclass typed"); 81 // here is the problem: the declared variable type is used 82 // but it should be infered by the compiler instead 83 Object a1 = new Asteroid("A1"); 84 Object a2 = new Asteroid("A2"); 85 Object s1 = new Spaceship("S1"); 86 Object s2 = new Spaceship("S2"); 87 colide(a1, a2); 88 colide(a1, s1); 89 colide(s1, a1); 90 colide(s1, s2); 91 } 92 } 93 static class Dynamic { 94 void colide(Asteroid x, Asteroid y) { 95 System.out.println("AA colide " + x.id() + " with " + y.id()); 96 } 97 void colide(Asteroid x, Spaceship y) { 98 System.out.println("AS colide " + x.id() + " with " + y.name()); 99 } 100 void colide(Spaceship x, Asteroid y) { 101 System.out.println("SA colide " + x.name() + " with " + y.id()); 102 } 103 void colide(Spaceship x, Spaceship y) { 104 System.out.println("SS colide " + x.name() + " with " + y.name()); 105 } 106 void colide(Object x, Object y) { 107 System.out.println("OO colide " + x + " with " + y); 108 } 109 void run() { 110 run1(); 111 run2(); 112 } 113 void run1() { 114 System.out.println("Dynamic: explicitly typed"); 115 Asteroid a1 = new Asteroid("A1"); 116 Asteroid a2 = new Asteroid("A2"); 117 Spaceship s1 = new Spaceship("S1"); 118 Spaceship s2 = new Spaceship("S2"); 119 colide(a1, a2); 120 colide(a1, s1); 121 colide(s1, a1); 122 colide(s1, s2); 123 } 124 void run2() { 125 System.out.println("Dynamic: superclass typed"); 126 // here is the problem: dispatch is on the declared 127 // variable type instead of the run-time value type 128 Object a1 = new Asteroid("A1"); 129 Object a2 = new Asteroid("A2"); 130 Object s1 = new Spaceship("S1"); 131 Object s2 = new Spaceship("S2"); 132 colide(a1, a2); 133 colide(a1, s1); 134 colide(s1, a1); 135 colide(s1, s2); 136 } 137 } 138 public static void main(String args[]) { 139 Static.run(); 140 new Dynamic().run(); 141 } 142 }