📄 tij0091.html
字号:
doesn’t show up. (The Java 1.2<A NAME="Index816"></A>
collections provide sorting functionality that solves this problem.)
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Inheritance
(
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>extends</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)
is used here to create a new type of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
– that is,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>SortVector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>is
a
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
with some added functionality. The use of inheritance here is powerful but it
presents problems. It turns out that some methods are
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(described
in Chapter 7), so you cannot override them. If you want to create a sorted
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that accepts and produces only
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">objects
you run into a wall, since
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>addElement( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>elementAt( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">are
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and these are precisely the methods you’d need to override so they accept
and produce only
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects. No luck there.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">On
the other hand, consider <A NAME="Index817"></A>composition:
the placing of an object
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>inside</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
a new class. Rather than rewrite the above code to accomplish this, we can
simply use a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>SortVector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
inside the new class. In this case, the inner class to implement the interface
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Compare
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">will
be created anonymously:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: StrSortVector.java</font>
<font color="#009900">// Automatically sorted Vector that </font>
<font color="#009900">// accepts and produces only Strings</font>
<font color="#0000ff">package</font> c08;
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> StrSortVector {
<font color="#0000ff">private</font> SortVector v = <font color="#0000ff">new</font> SortVector(
<font color="#009900">// Anonymous inner class:</font>
<font color="#0000ff">new</font> Compare() {
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font>
lessThan(Object l, Object r) {
<font color="#0000ff">return</font>
((String)l).toLowerCase().compareTo(
((String)r).toLowerCase()) < 0;
}
<font color="#0000ff">public</font> <font color="#0000ff">boolean</font>
lessThanOrEqual(Object l, Object r) {
<font color="#0000ff">return</font>
((String)l).toLowerCase().compareTo(
((String)r).toLowerCase()) <= 0;
}
}
);
<font color="#0000ff">private</font> <font color="#0000ff">boolean</font> sorted = <font color="#0000ff">false</font>;
<font color="#0000ff">public</font> <font color="#0000ff">void</font> addElement(String s) {
v.addElement(s);
sorted = <font color="#0000ff">false</font>;
}
<font color="#0000ff">public</font> String elementAt(<font color="#0000ff">int</font> index) {
<font color="#0000ff">if</font>(!sorted) {
v.sort();
sorted = <font color="#0000ff">true</font>;
}
<font color="#0000ff">return</font> (String)v.elementAt(index);
}
<font color="#0000ff">public</font> Enumeration elements() {
<font color="#0000ff">if</font>(!sorted) {
v.sort();
sorted = <font color="#0000ff">true</font>;
}
<font color="#0000ff">return</font> v.elements();
}
<font color="#009900">// Test it:</font>
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
StrSortVector sv = <font color="#0000ff">new</font> StrSortVector();
sv.addElement("d");
sv.addElement("A");
sv.addElement("C");
sv.addElement("c");
sv.addElement("b");
sv.addElement("B");
sv.addElement("D");
sv.addElement("a");
Enumeration e = sv.elements();
<font color="#0000ff">while</font>(e.hasMoreElements())
System.out.println(e.nextElement());
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
quickly reuses the code from
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>SortVector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to create the desired functionality. However, not all of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods from
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>SortVector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
appear in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>StrSortVector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
When reusing code this way, you can make a definition in the new class for each
one in the contained class, or you can start with just a few and periodically
go back and add more when you need them. Eventually the new class design will
settle down.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
advantage to this approach is that it will take only
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
String
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects and produce only
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
objects, and the checking happens at compile time instead of run time. Of
course, that’s only true for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>addElement( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>elementAt( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">;
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>elements( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
still produces an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Enumeration</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that is untyped at compile time. Type checking for the <A NAME="Index818"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Enumeration</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>StrSortVector</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
still happens, of course, it just happens at run-time by throwing exceptions if
you do something wrong. It’s a trade-off: do you find out about something
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>for
sure
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
at compile time or
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>probably</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
at run-time? (That is, “probably not while you’re testing the
code” and “probably when the program user tries something you
didn’t test for.”) Given the choices and the hassle, it’s
easier to use inheritance and just grit your teeth while casting – again,
if <A NAME="Index819"></A>parameterized
types are ever added to Java, they will solve this problem.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see there’s a flag called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>sorted</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in this class. You could sort the vector every time
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>addElement( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is called, and constantly keep it in a sorted state. But usually people add a
lot of elements to a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Vector
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">before
beginning to read it. So sorting after every
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>addElement( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
would be less efficient than waiting until someone wants to read the vector and
then sorting it, which is what is done here. The technique of delaying a
process until it is absolutely necessary is called <A NAME="Index820"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>lazy
evaluation
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
(There is an analogous technique called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>lazy
initialization
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
which waits until a field value is necessary before initializing it.)
</FONT><a name="_Toc408018576"></a><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0090.html">Prev</a> | <a href="tij0092.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -