📄 tij0179.html
字号:
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">since
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>tb[i]</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
produces a handle to the base type
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TypedBin</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">this
call will end up calling a different method depending on the type of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TypedBin</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that’s currently selected. That is the second dispatch.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Here’s
the base class for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TypedBin</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">:</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: TypedBin.java</font>
<font color="#009900">// Vector that knows how to grab the right type</font>
<font color="#0000ff">package</font> c16.doubledispatch;
<font color="#0000ff">import</font> c16.trash.*;
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">public</font> <font color="#0000ff">abstract</font> <font color="#0000ff">class</font> TypedBin {
Vector v = <font color="#0000ff">new</font> Vector();
<font color="#0000ff">protected</font> <font color="#0000ff">boolean</font> addIt(Trash t) {
v.addElement(t);
<font color="#0000ff">return</font> <font color="#0000ff">true</font>;
}
<font color="#0000ff">public</font> Enumeration elements() {
<font color="#0000ff">return</font> v.elements();
}
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font> add(DDAluminum a) {
<font color="#0000ff">return</font> <font color="#0000ff">false</font>;
}
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font> add(DDPaper a) {
<font color="#0000ff">return</font> <font color="#0000ff">false</font>;
}
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font> add(DDGlass a) {
<font color="#0000ff">return</font> <font color="#0000ff">false</font>;
}
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font> add(DDCardboard a) {
<font color="#0000ff">return</font> <font color="#0000ff">false</font>;
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see that the overloaded
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>add( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods all return
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>false</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
If the method is not overloaded in a derived class, it will continue to return
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>false</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and the caller (
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>addToBin( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
in this case) will assume that the current
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Trash</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object has not been added successfully to a collection, and continue searching
for the right collection.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
each of the subclasses of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TypedBin</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
only one overloaded method is overridden, according to the type of bin
that’s being created. For example,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CardboardBin</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
overrides
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>add(DDCardboard)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The overridden method adds the trash object to its collection and returns
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>true</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
while all the rest of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>add( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">methods
in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CardboardBin
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">continue
to return
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>false</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
since they haven’t been overridden. This is another case in which a
parameterized type mechanism in Java would allow automatic generation of code.
(With <A NAME="Index2997"></A><A NAME="Index2998"></A>C++
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>template</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s,
you wouldn’t have to explicitly write the subclasses or place the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>addToBin( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Trash</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.)
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Since
for this example the trash types have been customized and placed in a different
directory, you’ll need a different trash data file to make it work.
Here’s a possible
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>DDTrash.dat</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">:</FONT><P></DIV>
<font color="#990000"><PRE>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:66
c16.DoubleDispatch.DDAluminum:36
c16.DoubleDispatch.DDCardboard:22</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Here’s
the rest of the program:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: DoubleDispatch.java</font>
<font color="#009900">// Using multiple dispatching to handle more</font>
<font color="#009900">// than one unknown type during a method call.</font>
<font color="#0000ff">package</font> c16.doubledispatch;
<font color="#0000ff">import</font> c16.trash.*;
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">class</font> AluminumBin <font color="#0000ff">extends</font> TypedBin {
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font> add(DDAluminum a) {
<font color="#0000ff">return</font> addIt(a);
}
}
<font color="#0000ff">class</font> PaperBin <font color="#0000ff">extends</font> TypedBin {
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font> add(DDPaper a) {
<font color="#0000ff">return</font> addIt(a);
}
}
<font color="#0000ff">class</font> GlassBin <font color="#0000ff">extends</font> TypedBin {
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font> add(DDGlass a) {
<font color="#0000ff">return</font> addIt(a);
}
}
<font color="#0000ff">class</font> CardboardBin <font color="#0000ff">extends</font> TypedBin {
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font> add(DDCardboard a) {
<font color="#0000ff">return</font> addIt(a);
}
}
<font color="#0000ff">class</font> TrashBinSet {
<font color="#0000ff">private</font> TypedBin[] binSet = {
<font color="#0000ff">new</font> AluminumBin(),
<font color="#0000ff">new</font> PaperBin(),
<font color="#0000ff">new</font> GlassBin(),
<font color="#0000ff">new</font> CardboardBin()
};
<font color="#0000ff">public</font> <font color="#0000ff">void</font> sortIntoBins(Vector bin) {
Enumeration e = bin.elements();
<font color="#0000ff">while</font>(e.hasMoreElements()) {
TypedBinMember t =
(TypedBinMember)e.nextElement();
<font color="#0000ff">if</font>(!t.addToBin(binSet))
System.err.println("Couldn't add " + t);
}
}
<font color="#0000ff">public</font> TypedBin[] binSet() { <font color="#0000ff">return</font> binSet; }
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> DoubleDispatch {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Vector bin = <font color="#0000ff">new</font> Vector();
TrashBinSet bins = <font color="#0000ff">new</font> TrashBinSet();
<font color="#009900">// ParseTrash still works, without changes:</font>
ParseTrash.fillBin("DDTrash.dat", bin);
<font color="#009900">// Sort from the master bin into the </font>
<font color="#009900">// individually-typed bins:</font>
bins.sortIntoBins(bin);
TypedBin[] tb = bins.binSet();
<font color="#009900">// Perform sumValue for each bin...</font>
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < tb.length; i++)
Trash.sumValue(tb[i].v);
<font color="#009900">// ... and for the master bin</font>
Trash.sumValue(bin);
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TrashBinSet</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
encapsulates all of the different types of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TypedBin</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s,
along with the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sortIntoBins( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method, which is where all the double dispatching takes place. You can see that
once the structure is set up, sorting into the various
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TypedBin</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s
is remarkably easy. In addition, the efficiency of two dynamic method calls is
probably better than any other way you could sort.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Notice
the ease of use of this system in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
as well as the complete independence of any specific type information within
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
All other methods that talk only to the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Trash</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
base-class interface will be equally invulnerable to changes in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Trash</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
types.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
changes necessary to add a new type are relatively isolated: you inherit the
new type of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Trash</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
with its
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>addToBin( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method, then you inherit a new
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TypedBin</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(this is really just a copy and simple edit), and finally you add a new type
into the aggregate initialization for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>TrashBinSet</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><a name="_Toc408018805"></a><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0178.html">Prev</a> | <a href="tij0180.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -