📄 chapter06.html
字号:
<!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:Tjava14.rtf
Application Directory:c:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:02/04/2000
Translation Time:23:24:51
Translation Platform:Win32
Number of Output files:27
This File:Chapter06.html
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-head.gif" alt="MindView Inc." BORDER = "0"></a>
<CENTER>
<FONT FACE="Verdana" size = "-1">
[ <a href="README-HTML.txt">Viewing Hints</a> ]
[ <a href="http://www.mindview.net/TIJ2/index.html">2nd Edition</a> ]
[ <a href="http://www.mindview.net/MailingList.html">Free Newsletter</a> ] <br>
[ <a href="http://www.mindview.net/Training.html">Seminars</a> ]
[ <a href="http://www.mindview.net/javaCD2.html">Seminars on CD ROM</a> ]
[ <a href="http://www.mindview.net/CPPServices/#ConsultingServices">Consulting</a> ]
</FONT>
<H2><FONT FACE="Verdana">
Thinking in Java, 1st edition</FONT></H2>
<H3><FONT FACE="Verdana">©1998 by Bruce Eckel</FONT></H3>
<FONT FACE="Verdana" size = "-1">
[ <a href="Chapter05.html">Previous Chapter</a> ]
[ <a href="SimpleContents.html">Short TOC</a> ]
[ <a href="Contents.html">Table of Contents</a> ]
[ <a href="DocIndex.html">Index</a> ]
[ <a href="Chapter07.html">Next Chapter</a> ]
</FONT>
</CENTER>
</P></DIV><A NAME="Chapter_6"></A><A NAME="_Toc375545305"></A><A NAME="_Toc407441450"></A><A NAME="_Toc408018508"></A><A NAME="Heading179"></A><FONT FACE = "Verdana"><H1 ALIGN="LEFT">
6: Reusing classes</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" SIZE=4>One of the most
compelling features about Java is code
reuse<A NAME="Index423"></A><A NAME="Index424"></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.</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="Index425"></A>because the new class is composed of objects of existing
classes. You’re simply reusing the functionality of the code, not its
form.</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="Index426"></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 the next chapter.</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.</FONT><A NAME="_Toc305593251"></A><A NAME="_Toc305628723"></A><A NAME="_Toc312374014"></A><A NAME="_Toc375545306"></A><A NAME="_Toc408018509"></A><BR></P></DIV>
<A NAME="Heading180"></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 handles 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
non-primitive objects, just put handles inside your new class, and for the
primitives just define them inside your class:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: SprinklerSystem.java</font>
<font color=#009900>// Composition for code reuse</font>
<font color=#0000ff>package</font> c06;
<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 non-primitive object has a
<A NAME="Index427"></A><A NAME="Index428"></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="Index429"></A><A NAME="Index430"></A></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 handles 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="Index431"></A><A NAME="Index432"></A>initialized to zero, as noted in
Chapter 2. But the object handles 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.</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 handle because that would
incur unnecessary overhead in many cases. If you want the handles initialized,
you can do it:</FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Georgia"> At the point the objects are defined. This means
that they’ll always be initialized before the constructor is
called.</FONT><LI><FONT FACE="Georgia"> In the constructor for that
class</FONT><LI><FONT FACE="Georgia"> Right before you actually need to
use the object. This can reduce overhead, if there are situations where the
object doesn’t need to be
created.</FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">All three
approaches are shown here:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: Bath.java</font>
<font color=#009900>// Constructor initialization with composition</font>
<font color=#0000ff>class</font> Soap {
<font color=#0000ff>private</font> String s;
Soap() {
System.out.println(<font color=#004488>"Soap()"</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> Bath {
<font color=#0000ff>private</font> String
<font color=#009900>// Initializing at point of definition:</font>
s1 = <font color=#0000ff>new</font> String(<font color=#004488>"Happy"</font>),
s2 = <font color=#004488>"Happy"</font>,
s3, s4;
Soap castille;
<font color=#0000ff>int</font> i;
<font color=#0000ff>float</font> toy;
Bath() {
System.out.println(<font color=#004488>"Inside Bath()"</font>);
s3 = <font color=#0000ff>new</font> String(<font color=#004488>"Joy"</font>);
i = 47;
toy = 3.14f;
castille = <font color=#0000ff>new</font> Soap();
}
<font color=#0000ff>void</font> print() {
<font color=#009900>// Delayed initialization:</font>
<font color=#0000ff>if</font>(s4 == <font color=#0000ff>null</font>)
s4 = <font color=#0000ff>new</font> String(<font color=#004488>"Joy"</font>);
System.out.println(<font color=#004488>"s1 = "</font> + s1);
System.out.println(<font color=#004488>"s2 = "</font> + s2);
System.out.println(<font color=#004488>"s3 = "</font> + s3);
System.out.println(<font color=#004488>"s4 = "</font> + s4);
System.out.println(<font color=#004488>"i = "</font> + i);
System.out.println(<font color=#004488>"toy = "</font> + toy);
System.out.println(<font color=#004488>"castille = "</font> + castille);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -