Remember that polymorphism can only be represented by method calls, so if you want to make the double dispatch correct, you must perform two method calls:
In each structure, one is used to determine the type. In the trash structure, a new method is invoked to invoke Addtobin (), which takes a parameter that is an array composed of Typebin. The method will iterate through the array, trying to add itself to the appropriate garbage cans, where the double dispatch takes place.
The new hierarchical structure is Typebin, which contains one of its own methods, called Add (), and is also applied in the form of polymorphism. However, note that a new feature: Add () has been "overloaded" processing, can accept different types of garbage as parameters. Therefore, one of the key points of the dual satisfaction mechanism is that it also involves overload.
The redesign of the program also poses a problem: the current base class trash must contain a Addtobin () method. One of the most straightforward ways to solve this problem is to copy all the code and modify the underlying class. However, if there is no control over the source code, there is another way to consider: placing the Addtobin () method inside an interface, keeping the trash unchanged, and inheriting the new, special type Aluminum,paper,glass and cardboard. We are prepared to take the latter approach here.
Most of the classes used in this design must be set to public (common) properties, so they are placed in their own classes. The interface code is listed below:
: Typedbinmember.java
//an interface for adding the double dispatching/method to the Trash hierarchy without
//Modifying the original hierarchy.
Package c16.doubledispatch;
Interface Typedbinmember {
//The New method:
boolean addtobin (typedbin[] TB);
///:~
The Addtobin () method of the interface Typebinmember is implemented within each specific subtype of aluminum,paper,glass and cardboard, but the code used in each case "seems" to be exactly the same:
: Ddaluminum.java
//aluminum for double dispatching
package c16.doubledispatch;
Import c16.trash.*;
public class Ddaluminum extends aluminum
implements Typedbinmember {public
ddaluminum (double wt) {super (WT);} Public
Boolean addtobin (typedbin[] TB) {for
(int i = 0; i < tb.length i++)
if (Tb[i].add (this))
ret Urn true;
return false;
}
} ///:~
: Ddpaper.java
//Paper for double dispatching
package c16.doubledispatch;
Import c16.trash.*;
public class Ddpaper extends Paper
implements Typedbinmember {public
ddpaper (double wt) {super (WT);}
public boolean addtobin (typedbin[] TB) {for
(int i = 0; i < tb.length i++)
if (Tb[i].add (this)) return
t Rue;
return false;
}
} ///:~
: Ddglass.java
//Glass for double dispatching
package c16.doubledispatch;
Import c16.trash.*;
public class Ddglass extends Glass
implements Typedbinmember {public
ddglass (double wt) {super (WT);}
public boolean addtobin (typedbin[] TB) {for
(int i = 0; i < tb.length i++)
if (Tb[i].add (this)) return
TR UE;
return false;
}
} ///:~
: Ddcardboard.java
//cardboard for double dispatching
package c16.doubledispatch;
Import c16.trash.*;
public class Ddcardboard extends cardboard
implements Typedbinmember {public
ddcardboard (double wt) {super ( WT); Public
Boolean addtobin (typedbin[] TB) {for
(int i = 0; i < tb.length i++)
if (Tb[i].add (this))
return true;
return false;
}
} ///:~
The code within each addtobin () calls add () for each Typebin object in the array. But please note the parameters: this. For each subclass of trash, this is a different type, so you can't think of the code as "complete"-although you can think of it later in Java by adding a parameterized type mechanism. This is the first part of the double dispatch, because once you get inside this method, you can tell whether it's aluminum,paper or what kind of junk it is. In the invocation of Add (), this information is passed through the type of this. The compiler will parse the call to the correct overloaded version of Add (). However, because Tb[i] produces a handle to the underlying type Typebin, a different method will eventually be invoked-depending on the type of Typebin currently selected. That was the second dispatch.
The following is the base class for Typebin:
: Typedbin.java
//Vector that knows you to grab the right type
package c16.doubledispatch;
Import c16.trash.*;
Import java.util.*;
Public abstract class Typedbin {
vector v = new vector ();
Protected Boolean Addit (Trash t) {
v.addelement (t);
return true;
}
Public enumeration elements () {return
v.elements ();
}
Public boolean Add (Ddaluminum a) {return
false;
}
Public boolean Add (Ddpaper a) {return
false;
}
Public boolean Add (Ddglass a) {return
false;
}
Public boolean Add (Ddcardboard a) {return
false;
}
}///:~
You can see that all the overload add () methods return false. If the method is not overloaded in the derived class, it returns FALSE, and the caller (currently Addtobin ()) considers that the current trash object has not successfully joined a collection, so it continues to find the correct collection.
in each subclass of Typebin, only one overload method is overloaded-depending on what type of garbage bin is being created. For example, Cardboardbin will overload add (Ddcardboard). An overloaded method adds a garbage object to its collection and returns True. All the Add () methods remaining in the Cardboardbin continue to return false because they are not overloaded. In fact, if the parameterized type mechanism is used here, the automatic creation of Java code is much more convenient (using C + + "template", we do not have to bother to encode the subclass, or the Addtobin () method into the trash; Java has yet to be improved in this regard).
Because for this example, the type of garbage has been customized and placed in a different directory, so it needs to be run with a different junk data file. Here is a demonstration of the DDTrash.dat:
C16. doubledispatch.ddglass:54 C16. Doubledispatch.ddpaper:22 C16. Doubledispatch.ddpaper:11 C16. Doubledispatch.ddglass:17 C16. doubledispatch.ddaluminum:89 C16. Doubledispatch.ddpaper:88 C16. doubledispatch.ddaluminum:76 C16. doubledispatch.ddcardboard:96 C16. Doubledispatch.ddaluminum:25 C16. Doubledispatch.ddaluminum:34 C16. Doubledispatch.ddglass:11 C16. doubledispatch.ddglass:68 C16. doubledispatch.ddglass:43 C16. Doubledispatch.ddaluminum:27 C16. Doubledispatch.ddcardboard:44 C16. Doubledispatch.ddaluminum:18 C16. doubledispatch.ddpaper:91 C16. doubledispatch.ddglass:63 C16. Doubledispatch.ddglass:50 C16. Doubledispatch.ddglass:80 C16. doubledispatch.ddaluminum:81 C16. Doubledispatch.ddcardboard:12 C16. Doubledispatch.ddglass:12 C16. doubledispatch.ddglass:54 C16. Doubledispatch.ddaluminum:36 C16. doubledispatch.ddaluminum:93 C16. doubledispatch.ddglass:93 C16. Doubledispatch.ddpaper:80 C16. Doubledispatch.ddglass:36 C16. Doubledispatch.ddglass:12 C16. Doubledispatch.ddglass:60 C16.
doubledispatch.ddpaper:66C16. Doubledispatch.ddaluminum:36 C16. Doubledispatch.ddcardboard:22
The remaining parts of the program are listed under
:
: Doubledispatch.java//Using multiple dispatching to handle more//than one unknown type during a.
Package c16.doubledispatch;
Import c16.trash.*;
Import java.util.*;
Class Aluminumbin extends Typedbin {public boolean add (Ddaluminum a) {return Addit (a);
} class PaperBin extends Typedbin {public boolean add (Ddpaper a) {return Addit (a);
} class Glassbin extends Typedbin {public boolean add (Ddglass a) {return Addit (a);
} class Cardboardbin extends Typedbin {public boolean add (Ddcardboard a) {return Addit (a);
} class Trashbinset {private typedbin[] Binset = {new Aluminumbin (), New PaperBin (), New Glassbin (),
New Cardboardbin ()};
public void Sortintobins (Vector bin) {Enumeration e = Bin.elements ();
while (E.hasmoreelements ()) {Typedbinmember T = (typedbinmember) e.nextelement ();
if (!t.addtobin (Binset)) System.err.println ("couldn ' t add" + t); }} PubliC typedbin[] Binset () {return binset;}}
public class Doubledispatch {public static void main (string[] args) {Vector bin = new vector ();
Trashbinset bins = new Trashbinset ();
Parsetrash still works, without Changes:ParseTrash.fillBin ("DDTrash.dat", bin);
Sort from the master bin into the//individually-typed bins:bins.sortIntoBins (BIN);
typedbin[] TB = Bins.binset ();
Perform sumvalue for each bin ... for (int i = 0; i < tb.length; i++) Trash.sumvalue (TB[I].V);
... and for the Master Bin Trash.sumvalue (BIN); }
} ///:~
Trashbinset encapsulates various types of typebin, along with Sortintobins () methods. All the double dispatch events will happen in that way. As you can see, once you've set up your structure, it's easy to classify yourself as a variety of typebin. In addition, the efficiency of two dynamic method invocations may be higher than other sorting methods.
Note that the convenience of this system is mainly embodied in main (), while noting that any particular type of information is completely independent in main (). All other methods that communicate only with the Trash base class interface are not interfered with by the changes that occur in the trash class.
The changes that are required to add a new type are completely isolated: we inherit the new type of trash with the Addtobin () method, and then inherit a new Typebin (which is actually just a copy that can be edited simply), Finally, a new type of Trashbinset is added to the set initialization process.