⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap06.htm

📁 java书籍《thinking in java》
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<backtalk:display ID=TIJ3_CHAPTER6_I39>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Sometimes it makes sense to allow the
class user to directly access the composition of your new class; that is, to
make the member objects <B>public</B>. The member objects use implementation
hiding themselves, so this is a safe thing to do. When the user knows
you&#8217;re assembling a bunch of parts, it makes the interface easier to
understand. A <B>car</B> object is a good example:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c06:Car.java</font>
<font color=#009900>// Composition with public objects.</font>

<font color=#0000ff>class</font> Engine {
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> start() {}
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> rev() {}
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> stop() {}
}

<font color=#0000ff>class</font> Wheel {
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> inflate(<font color=#0000ff>int</font> psi) {}
}

<font color=#0000ff>class</font> Window {
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> rollup() {}
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> rolldown() {}
}

<font color=#0000ff>class</font> Door {
  <font color=#0000ff>public</font> Window window = <font color=#0000ff>new</font> Window();
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> open() {}
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> close() {}
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Car {
  <font color=#0000ff>public</font> Engine engine = <font color=#0000ff>new</font> Engine();
  <font color=#0000ff>public</font> Wheel[] wheel = <font color=#0000ff>new</font> Wheel[4];
  <font color=#0000ff>public</font> Door left = <font color=#0000ff>new</font> Door(),
       right = <font color=#0000ff>new</font> Door(); <font color=#009900>// 2-door</font>
  <font color=#0000ff>public</font> Car() {
    <font color=#0000ff>for</font>(<font color=#0000ff>int</font> i = 0; i &lt; 4; i++)
      wheel[i] = <font color=#0000ff>new</font> Wheel();
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Car car = <font color=#0000ff>new</font> Car();
    car.left.window.rollup();
    car.wheel[0].inflate(72);
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Because the composition of a car is part
of the analysis of the problem (and not simply part of the underlying design),
making the members <B>public</B> assists the client programmer&#8217;s
understanding of how to use the class and requires less code complexity for the
creator of the class. However, keep in mind that this is a special case and that
in general you should make fields <B>private</B>.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I39' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I40>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><A NAME="Index602"></A><A NAME="Index603"></A><FONT FACE="Georgia">When
you inherit, you take an existing class and make a special version of it. In
general, this means that you&#8217;re taking a general-purpose class and
specializing it for a particular need. With a little thought, you&#8217;ll see
that it would make no sense to compose a car using a vehicle object&#8212;a car
doesn&#8217;t contain a vehicle, it <I>is</I> a vehicle. The
<A NAME="Index604"></A><I>is-a</I> relationship is expressed with inheritance,
and the <A NAME="Index605"></A><I>has-a</I> relationship is expressed with
composition.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I40' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I41>
</FONT><A NAME="_Toc305593256"></A><A NAME="_Toc305628728"></A><A NAME="_Toc312374027"></A><A NAME="_Toc375545313"></A><A NAME="_Toc481064611"></A><BR></P></DIV>
<A NAME="Heading217"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
protected</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Now that you&#8217;ve been introduced to
inheritance, the keyword <B>protected<A NAME="Index606"></A></B> finally has
meaning. In an ideal world, <B>private</B> members would always be hard-and-fast
<B>private</B>, but in real projects there are times when you want to make
something hidden from the world at large and yet allow access for members of
derived classes. The <B>protected</B> keyword is a nod to pragmatism. It says
&#8220;This is <B>private</B> as far as the class user is concerned, but
available to anyone who inherits from this class or anyone else in the same
<B>package</B>.&#8221; That is,
<A NAME="Index607"></A><A NAME="Index608"></A><B>protected</B> in Java is
automatically &#8220;friendly.&#8221;

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I41' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I42>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The best tack to take is to leave the
data members <A NAME="Index609"></A><B>private</B>&#8212;you should always
preserve your right to change the underlying implementation. You can then allow
controlled access to inheritors of your class through
<A NAME="Index610"></A><B>protected </B>methods:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c06:Orc.java</font>
<font color=#009900>// The protected keyword.</font>
<font color=#0000ff>import</font> java.util.*;

<font color=#0000ff>class</font> Villain {
  <font color=#0000ff>private</font> <font color=#0000ff>int</font> i;
  <font color=#0000ff>protected</font> <font color=#0000ff>int</font> read() { <font color=#0000ff>return</font> i; }
  <font color=#0000ff>protected</font> <font color=#0000ff>void</font> set(<font color=#0000ff>int</font> ii) { i = ii; }
  <font color=#0000ff>public</font> Villain(<font color=#0000ff>int</font> ii) { i = ii; }
  <font color=#0000ff>public</font> <font color=#0000ff>int</font> value(<font color=#0000ff>int</font> m) { <font color=#0000ff>return</font> m*i; }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Orc <font color=#0000ff>extends</font> Villain {
  <font color=#0000ff>private</font> <font color=#0000ff>int</font> j;
  <font color=#0000ff>public</font> Orc(<font color=#0000ff>int</font> jj) { <font color=#0000ff>super</font>(jj); j = jj; }
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> change(<font color=#0000ff>int</font> x) { set(x); }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can see that <B>change(&#160;)</B>
has access to <B>set(&#160;)</B> because it&#8217;s <B>protected</B>.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I42' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I43>
</FONT><A NAME="_Toc305593258"></A><A NAME="_Toc305628730"></A><A NAME="_Toc312374030"></A><A NAME="_Toc375545314"></A><A NAME="_Toc481064612"></A><BR></P></DIV>
<A NAME="Heading218"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Incremental development</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">One of the advantages of inheritance is
that it supports <I>incremental
development<A NAME="Index611"></A><A NAME="Index612"></A></I> by allowing you to
introduce new code without causing bugs in existing code. This also isolates new
bugs inside the new code. By inheriting from an existing, functional class and
adding data members and methods (and redefining existing methods), you leave the
existing code&#8212;that someone else might still be using&#8212;untouched and
unbugged. If a bug happens, you know that it&#8217;s in your new code, which is
much shorter and easier to read than if you had modified the body of existing
code. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I43' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I44>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It&#8217;s rather amazing how cleanly the
classes are separated. You don&#8217;t even need the source code for the methods
in order to reuse the code. At most, you just import a package. (This is true
for both inheritance and composition.)

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I44' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I45>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It&#8217;s important to realize that
program development is an incremental process, just like human learning. You can
do as much analysis as you want, but you still won&#8217;t know all the answers
when you set out on a project. You&#8217;ll have much more success&#8212;and
more immediate feedback&#8212;if you start out to &#8220;grow&#8221; your
project as an organic, evolutionary creature, rather than constructing it all at
once like a glass-box skyscraper.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I45' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I46>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Although inheritance for experimentation
can be a useful technique, at some point after things stabilize you need to take
a new look at your class hierarchy with an eye to collapsing it into a sensible
structure. Remember that underneath it all, inheritance is meant to express a
relationship that says &#8220;This new class is a <I>type of</I> that old
class.&#8221; Your program should not be concerned with pushing bits around, but
instead with creating and manipulating objects of various types to express a
model in the terms that come from the <A NAME="Index613"></A>problem space.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I46' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I47>
</FONT><A NAME="_Toc305593259"></A><A NAME="_Toc305628731"></A><A NAME="_Toc312374031"></A><A NAME="_Toc375545315"></A><A NAME="_Toc481064613"></A><BR></P></DIV>
<A NAME="Heading219"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Upcasting<BR><A NAME="Index614"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The most important aspect of inheritance
is not that it provides methods for the new class. It&#8217;s the relationship
expressed between the new class and the base class. This
<A NAME="Index615"></A>relationship can be summarized by saying &#8220;The new
class <I>is a type of</I> the existing class.&#8221; 

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I47' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I48>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This description is not just a fanciful
way of explaining inheritance&#8212;it&#8217;s supported directly by the
language. As an example, consider a base class called <B>Instrument</B> that
represents musical instruments, and a derived class called <B>Wind</B>. Because
inheritance means that all of the methods in the base class are also available
in the derived class, any message you can send to the base class can also be
sent to the derived class. If the <B>Instrument</B> class has a
<B>play(&#160;)</B> method, so will <B>Wind</B> instruments. This means we can
accurately say that a <B>Wind</B> object is also a type of <B>Instrument</B>.
The following example shows how the compiler supports this
notion:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c06:Wind.java</font>
<font color=#009900>// Inheritance &amp; upcasting.</font>
<font color=#0000ff>import</font> java.util.*;

<font color=#0000ff>class</font> Instrument {
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> play() {}
  <font color=#0000ff>static</font> <font color=#0000ff>void</font> tune(Instrument i) {
    <font color=#009900>// ...</font>
    i.play();
  }
}

<font color=#009900>// Wind objects are instruments</font>
<font color=#009900>// because they have the same interface:</font>
<font color=#0000ff>public</font> <font color=#0000ff>class</font> Wind <font color=#0000ff>extends</font> Instrument {
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Wind flute = <font color=#0000ff>new</font> Wind();
    Instrument.tune(flute); <font color=#009900>// Upcasting</font>
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">What&#8217;s interesting in this example
is the <B>tune(&#160;)</B> method, which accepts an <B>Instrument</B> reference.
However, in <B>Wind</B>.<B>main(&#160;)</B> the <B>tune(&#160;)</B> method is
called by giving it a <B>Wind</B> reference. Given that Java is particular about
type checking, it seems strange that a method that accepts one type will readily
accept another type, until you realize that a <B>Wind</B> object is also an
<B>Instrument</B> object, and there&#8217;s no method that <B>tune(&#160;)</B>
could call for an <B>Instrument</B> that isn&#8217;t also in <B>Wind</B>. Inside
<B>tune(&#160;)</B>, the code works for <B>Instrument</B> and anything derived
from <B>Instrument</B>, and the act of converting a <B>Wind</B> reference into
an <B>Instrument</B> reference is called <I>upcasting</I>.

</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I48' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I49>
</FONT><A NAME="_Toc312374032"></A><A NAME="_Toc375545316"></A><A

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -