📄 chap06.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source:
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:TIJ2.rtf
Application Directory:C:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:05/21/2001
Translation Time:10:39:08
Translation Platform:Win32
Number of Output files:23
This File:Chap06.htm
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>6: Reusing Classes</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
<a href="http://www.MindView.net">
<img src="mindview.gif" alt="MindView Inc." BORDER = "0"></a>
<CENTER>
<FONT FACE="Verdana" size = "-1">
[ <a href="README.txt">Viewing Hints</a> ]
[ <a href="RevHist.htm">Revision History</a> ]
[ <a href="http://www.mindview.net/Books/TIJ/">Book Home Page</a> ]
[ <a href="http://www.mindview.net/Etc/MailingList.html">Free Newsletter</a> ] <br>
[ <a href="http://www.mindview.net/Seminars">Seminars</a> ]
[ <a href="http://www.mindview.net/CDs">Seminars on CD ROM</a> ]
[ <a href="http://www.mindview.net/Services">Consulting</a> ]
</FONT>
<H2><FONT FACE="Verdana">
Thinking in Java, 2nd edition, Revision 12</FONT></H2>
<H3><FONT FACE="Verdana">©2000 by Bruce Eckel</FONT></H3>
<FONT FACE="Verdana" size = "-1">
[ <a href="Chap05.htm">Previous Chapter</a> ]
[ <a href="SimpCont.htm">Short TOC</a> ]
[ <a href="Contents.htm">Table of Contents</a> ]
[ <a href="DocIdx.htm">Index</a> ]
[ <a href="Chap07.htm">Next Chapter</a> ]
</FONT>
</CENTER>
</P></DIV><A NAME="Chapter_6"></A><A NAME="_Toc375545305"></A><A NAME="_Toc477690726"></A><A NAME="_Toc481064603"></A><A NAME="Heading206"></A><FONT FACE = "Verdana"><H1 ALIGN="LEFT">
6: Reusing Classes</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia" SIZE=4><backtalk:display ID=TIJ3_CHAPTER6_I0>
One of
the most compelling features about Java is code
reuse<A NAME="Index541"></A><A NAME="Index542"></A>. But to be revolutionary,
you’ve got to be able to do a lot more than copy code and change
it.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">That’s the approach used in
procedural languages like C, and it hasn’t worked very well. Like
everything in Java, the solution revolves around the class. You reuse code by
creating new classes, but instead of creating them from scratch, you use
existing classes that someone has already built and debugged.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I0'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER6_I1>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The trick is to use the classes without
soiling the existing code. In this chapter you’ll see two ways to
accomplish this. The first is quite straightforward: You simply create objects
of your existing class inside the new class. This is called <I>composition,</I>
<A NAME="Index543"></A>because the new class is composed of objects of existing
classes. You’re simply reusing the functionality of the code, not its
form.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I1'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER6_I2>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The second approach is more subtle. It
creates a new class as a <I>type of</I> an existing class. You literally take
the form of the existing class and add code to it without modifying the existing
class. This magical act is called <I>inheritance<A NAME="Index544"></A></I>, and
the compiler does most of the work. Inheritance is one of the cornerstones of
object-oriented programming, and has additional implications that will be
explored in Chapter 7.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I2'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER6_I3>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It turns out that much of the syntax and
behavior are similar for both composition and inheritance (which makes sense
because they are both ways of making new types from existing types). In this
chapter, you’ll learn about these code reuse mechanisms.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I3'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER6_I4>
</FONT><A NAME="_Toc305593251"></A><A NAME="_Toc305628723"></A><A NAME="_Toc312374014"></A><A NAME="_Toc375545306"></A><A NAME="_Toc481064604"></A><BR></P></DIV>
<A NAME="Heading207"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Composition syntax</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Until now, composition has been used
quite frequently. You simply place object references inside new classes. For
example, suppose you’d like an object that holds several <B>String</B>
objects, a couple of primitives, and an object of another class. For the
nonprimitive objects, you put references inside your new class, but you define
the primitives directly:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c06:SprinklerSystem.java</font>
<font color=#009900>// Composition for code reuse.</font>
<font color=#0000ff>class</font> WaterSource {
<font color=#0000ff>private</font> String s;
WaterSource() {
System.out.println(<font color=#004488>"WaterSource()"</font>);
s = <font color=#0000ff>new</font> String(<font color=#004488>"Constructed"</font>);
}
<font color=#0000ff>public</font> String toString() { <font color=#0000ff>return</font> s; }
}
<font color=#0000ff>public</font> <font color=#0000ff>class</font> SprinklerSystem {
<font color=#0000ff>private</font> String valve1, valve2, valve3, valve4;
WaterSource source;
<font color=#0000ff>int</font> i;
<font color=#0000ff>float</font> f;
<font color=#0000ff>void</font> print() {
System.out.println(<font color=#004488>"valve1 = "</font> + valve1);
System.out.println(<font color=#004488>"valve2 = "</font> + valve2);
System.out.println(<font color=#004488>"valve3 = "</font> + valve3);
System.out.println(<font color=#004488>"valve4 = "</font> + valve4);
System.out.println(<font color=#004488>"i = "</font> + i);
System.out.println(<font color=#004488>"f = "</font> + f);
System.out.println(<font color=#004488>"source = "</font> + source);
}
<font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
SprinklerSystem x = <font color=#0000ff>new</font> SprinklerSystem();
x.print();
}
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">One of the methods defined in
<B>WaterSource </B>is special: <B>toString( )</B>. You will learn later
that every nonprimitive object has a
<A NAME="Index545"></A><A NAME="Index546"></A><B>toString( )</B> method,
and it’s called in special situations when the compiler wants a
<B>String</B> but it’s got one of these objects. So in the
expression:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>System.out.println(<font color=#004488>"source = "</font> + source);</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">the compiler sees you trying to add a
<B>String</B> object ("<B>source = </B>") to a <B>WaterSource</B>. This
doesn’t make sense to it, because you can only “add” a
<B>String</B> to another <B>String</B>, so it says “I’ll turn
<B>source</B> into a <B>String</B> by calling <B>toString( )</B>!”
After doing this it can combine the two <B>String</B>s and pass the resulting
<B>String</B> to <B>System.out.println( )</B>. Any time you want to allow
this behavior with a class you create you need only write a
<B>toString( )</B> method. <A NAME="Index547"></A><A NAME="Index548"></A>
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I4'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER6_I5>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">At first glance, you might
assume—Java being as safe and careful as it is—that the compiler
would automatically construct objects for each of the references in the above
code; for example, calling the default constructor for <B>WaterSource</B> to
initialize <B>source</B>. The output of the print statement is in
fact:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>valve1 = <font color=#0000ff>null</font>
valve2 = <font color=#0000ff>null</font>
valve3 = <font color=#0000ff>null</font>
valve4 = <font color=#0000ff>null</font>
i = 0
f = 0.0
source = <font color=#0000ff>null</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Primitives that are fields in a class are
automatically <A NAME="Index549"></A><A NAME="Index550"></A>initialized to zero,
as noted in Chapter 2. But the object references are initialized to <B>null</B>,
and if you try to call methods for any of them you’ll get an exception.
It’s actually pretty good (and useful) that you can still print them out
without throwing an exception.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I5'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER6_I6>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It makes sense that the compiler
doesn’t just create a default object for every reference because that
would incur unnecessary overhead in many cases. If you want the references
initialized, you can do it:
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I6'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER6_I7>
</FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Verdana"> </FONT><FONT FACE="Georgia">At the point the objects
are defined. This means that they’ll always be initialized before the
constructor is called.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I7'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER6_I8>
</FONT><LI><FONT FACE="Verdana"> </FONT><FONT FACE="Georgia">In
the constructor for that class.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I8'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER6_I9>
</FONT><LI><FONT FACE="Verdana"> </FONT><FONT FACE="Georgia">Right
before you actually need to use the object. This is often called <I>lazy
initializatio</I></FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><I>n<A NAME="Index551"></A><A NAME="Index552"></A></I>.
It can reduce overhead in situations where the object doesn’t need to be
created every time.
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I9'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER6_I10>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">All three approaches are shown here:
</backtalk:display>
[ <a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I10'
target="_blank">Add Comment</a> ]
<backtalk:display ID=TIJ3_CHAPTER6_I11>
</FONT><BR></P></DIV>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -