Simulate Double Dispatch in Java

Source: Internet
Author: User

Simulate Double Dispatch in Java

This section uses the command mode to simulate double dispatch in Java. After understanding this section,Visitor pattern)Hand to hand.

1. Single Assignment

Dispatch/dispatch is how to bind a message to its method body. Java and C # are supported onlySingledispatch)Double dispatch is not supported ). [Concepts, see design patterns. 5.11 visitor patterns p223]

For MessagesA. foo (B)Assume that there are parent class X and its two sub-classes X1 and X2, a is declared as X type variables, parent class Y and its two sub-classes Y1 and Y2, and B is declared as Y type variables, in addition, the foo (Y), foo (Y1), AND foo (Y2) methods have been prepared for both X, X1, and X2. Could you tell me. which of the 3*3 = 9 methods will be executed by foo (B?

Currently, mainstream object-oriented languages such as C ++, Java, and C # Only supportSingledispatch). In Example 3-18, we can ignore parameter B in a. foo (B). We just want to check the message a. m. Assume that m () is prepared for both X, X1, and X2, then a. m () binds its override method body according to the actual type of a, which is the object-orientedDynamic binding.

The so-called double dispatch is the hopeA. Foo (B) Can ① bind its override method body according to the actual type of a, and can ②Bind according to the actual type of BItsReloadThe method is the appropriate method body in foo (Y), foo (Y1), foo (Y2. Obviously, Java does not support the latter-that is, it does not support double dispatch. During Java compilation, foo (B) is declared as B.Static bindingThe method body foo (Y. For more information about the matching algorithms of Java overload methods, see [Introduction to programming · 2. 3.1 ].

Routine 3 18: Dispatch package method. command. doubleDispatch; import static tool. print. *; public abstract class X {public void m () {pln ("X. m () ");} public void foo (X x X) {p (" X. foo (X)-"); x. m ();} public void foo (X1 x1) {p ("X. foo (X1)-"); x1.m ();} // foo (X2 x2) slightly} // code of sub-classes X1 and X2, slightly package method. command. doubleDispatch; import tool. god; public class Test {public static void X single assignment () {X a = (X) God. create ("3-18-X1"); X B = (X) God. create ("3-18-X2");. m ();. foo (B );}}
For simplicity, the types of a and B in the message a. foo (B) are X. Double dispatch Message Receiver a and parameter BOf Runtime type (actual type)For binding, Javabu supports. To illustrate this point, the code above shows that X contains foo (X), foo (X1), AND foo (X2) method (parent class X depends on its subclass), and the override of subclass X1 and X2 contains the overloaded foo () method code.

Result of Test. X single dispatch:

X1.m () // dynamic binding

X1.foo (X)-X2.m () // dynamically bind foo of X1, and statically bind foo (X ).

Then, the running result of B. foo (: X2.foo (X)-X1.m ()


It is clear that the dynamic binding of rewriting and the static binding of reload are clear, that is, Java supports single-assignment rather than double-assignment, write Y, Y1, and Y2 in the following code to retain only the m () prepared by them, and delete the foo methods in the Y series in the OverloadFoo class.FocusHow to simulate double dispatch.

package method.command.doubleDispatch;import static tool.Print.*;public class Y{    public void m(){        pln(" Y.m()");    }}
package method.command.doubleDispatch;import static tool.Print.*;public class Y1 extends Y{    @Override public void m(){        pln("Y1.m()");    }}
package method.command.doubleDispatch;import static tool.Print.*;/** * OverloadFoo.java. *  * @author yqj2065 * @version 0.1 */public class OverloadFoo{    public void foo(Y y) { y.m();pln("foo(Y)"); }    public void foo(Y1 y){ y.m();pln("foo(Y1)");}    public void foo(Y2 y){ y.m();pln("foo(Y2)");}    /**     * (Run-Time Type Identification、RTTI     */    public void foo_RTTI(Y y){        if(y instanceof Y1){            pln("foo(Y1)");        }else if(y instanceof Y2){            pln("foo(Y2)");        }else{            pln("foo(Y)");         }    }}
Java can be used Run-Time TypeIdentification and RTTI)Technology uses the keyword instanceof to determine the actual type. Therefore, one privilege is to delete three overloaded foo () methods, and write the foo_RTTI (Y) method ). Although foo_RTTI (Y) code is concise, It is not elegant to use branch statements.

If you use if-else everywhere, many models will be unemployed.

2. Command mode to distinguish between overloaded Methods

[Introduction to programming · 2. 3.1]: "To reload a method, the real thing to do is to define several different methods, but 'coincidentally 'uses the same method name ".

Call the module of foo (Y), such as Test. In its view, it can overload foo (X), foo (X1), foo (X2), fooX () and fooX1 () with different names () or fooX2 (). Test wants to make a unified call -- ignore the called method name. We can use the command mode.

Package method. command. doubleDispatch; public abstract class Command {OverloadFoo handler = new OverloadFoo (); public abstract void foo (Y y Y); // change: Executor knows OverloadFoo}
Package method. command. doubleDispatch; public class FooY1 extends Command {@ Override public void foo (Y y) {handler. foo (Y1) y);} // FooY and FooY2
In this Command and 3.4 Command mode (5.2), the simple Command interface has some minor improvements: the executor of the Command is known to be OverloadFoo (because it includes three overloaded foo methods ); the abstract method foo has parameters.

The sub-class FooY1 of Command, indicating that the executor calls the overloaded foo (Y1) method.

Public static void simulate double dispatch () {Y y = (Y) God. create ("3-18-Y"); // Y1 object Command cmd = new FooY (); cmd. foo (y); cmd = new FooY1 (); cmd. foo (y); cmd = new FooY2 (); // The task cannot be executed // cmd. foo (y );}
Now, after creating an Y object (actual type Y1), run the following command to test the result:

Y1.m ()
Foo (Y)
Y1.m ()
Foo (Y1)

The command mode allows the user class Test to disregard the called method name and issue the unified command foo (y). The performer follows the different command objects, execute different method bodies -- here we will distinguish the overloaded methods.


Figure 1 Application Command mode

3. Merge class levels

There are two class hierarchies Y and Command, and the graph looks complicated. We found that the code of the universal Command foo (Y y Y) in its subclass FooY1 is:

@ Override public void foo (Y y ){
Handler. fOo (Y1) y ); <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> Examples/wxsd1_m3xqru7xnijv9kqteo + zcrHPHN0cm9uZz7D/examples + samples/samples + jrMbVysrD/samples + labels = "brush: java;"> package method. command. doubleDispatch; public interface Foo {public void handleFoo ();}The Z corresponding to X and Y, which is different from X Foo (Foo)!

The class hierarchy of Z is the child type of Command/Foo.. Z implements Foo makes the sub-classes of Z automatically become the sub-types of Foo (in fact, Z itself does not need to be the sub-types of Foo, you can set all sub-classes of Z Z1, Z2 implements Foo)

Package method. command. doubleDispatch; import static tool. print. *; public abstract class Z implements Foo {public void m () {pln ("Z. m () ");} public void foo (Foo z) {// sample code, which can be an empty method body p (" Z. foo (Foo)-"); this. m ();} // @ Override public void handleFoo () {}// optional}
The Z1 code is as follows:

Package method. command. doubleDispatch; import static tool. print. *; public class Z1 extends Z {@ Override public void m () {pln ("Z1.m ()") ;}/ * In fact, it means to overload foo (Z1) */@ Override public void foo (Foo z) {p ("Z1."); z. handleFoo (); // executor z dynamically binds this. m ();} private void foo () {p ("foo (Z1)-") ;}@ Override public void handleFoo () {this. foo ();}}
Package method. command. doubleDispatch; import tool. god; public class Test {public static void Z dual dispatch () {Z z1 = (Z) God. create ("3-18-Z1"); // Z1 Object Z z2 = (Z) God. create ("3-18-Z2"); // Z1 object z1.foo (z1); z1.foo (z2); z2.foo (z1); z2.foo (z2 );}}
Test results:

Z1.foo (Z1)-Z1.m ()
Z1.foo (Z2)-Z1.m ()
Z2.foo (Z1)-Z2.m ()
Z2.foo (Z2)-Z2.m ()

For MessagesA. foo (B)Assume that a and B are declared as Z-type variables.SimulationDouble Dispatch.

Figure 2 simple dual-Allocation Structure

This is a useful structure, which we can callDouble dispatch Mode., Is it awesome?

However, some annoying guys, they are even more awesome. In their own books, they refer to the "Double distribution" modelVisitor Mode!

You can modify the above Code to make the messageA. foo (B)Where a is declared as X type variable, B is declared as Z type variable.

According to the simulated dual-allocation model, the expression is 2*2, which is a superposition of two steps to form four processing processes. There is no dual-allocation mechanism, so it is differentiatedReload operations are not feasibleFor objects X1 and X2, The Methods fooZ1 (Z1) and fooZ2 (Z2) are required, which correspond to a. foo (B) and have four method bodies.


Returned directory

Last Edit Time: 2014.8.31

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.