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

📄 chap06.htm

📁 java书籍《thinking in java》
💻 HTM
📖 第 1 页 / 共 5 页
字号:
available in <B>Cleanser</B> as well as in <B>Detergent </B>(i.e.,
<B>foam(&#160;)</B>).

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

<backtalk:display ID=TIJ3_CHAPTER6_I23>
</FONT><A NAME="_Toc375545308"></A><A NAME="_Toc481064606"></A><BR></P></DIV>
<A NAME="Heading209"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Initializing the base
class<BR><A NAME="Index567"></A><A NAME="Index568"></A><A NAME="Index569"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Since there are now two classes
involved&#8212;the base class and the
<A NAME="Index570"></A><A NAME="Index571"></A>derived class&#8212;instead of
just one, it can be a bit confusing to try to imagine the resulting object
produced by a derived class. From the outside, it looks like the new class has
the same interface as the base class and maybe some additional methods and
fields. But inheritance doesn&#8217;t just copy the interface of the base class.
When you create an object of the derived class, it contains within it a
<I>subobject</I> of the base class. This
<A NAME="Index572"></A><A NAME="Index573"></A>subobject is the same as if you
had created an object of the base class by itself. It&#8217;s just that, from
the outside, the subobject of the base class is wrapped within the derived-class
object. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I23' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I24>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Of course, it&#8217;s essential that the
base-class subobject be initialized correctly and there&#8217;s only one way to
guarantee that: perform the initialization in the constructor, by calling the
base-class constructor, which has all the appropriate knowledge and privileges
to perform the base-class initialization. Java automatically inserts calls to
the base-class constructor in the derived-class constructor. The following
example shows this working with three levels of inheritance:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c06:Cartoon.java</font>
<font color=#009900>// Constructor calls during inheritance.</font>

<font color=#0000ff>class</font> Art {
  Art() {
    System.out.println(<font color=#004488>"Art constructor"</font>);
  }
}

<font color=#0000ff>class</font> Drawing <font color=#0000ff>extends</font> Art {
  Drawing() {
    System.out.println(<font color=#004488>"Drawing constructor"</font>);
  }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Cartoon <font color=#0000ff>extends</font> Drawing {
  Cartoon() {
    System.out.println(<font color=#004488>"Cartoon constructor"</font>);
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Cartoon x = <font color=#0000ff>new</font> Cartoon();
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The output for this program shows the
automatic calls:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Art constructor
Drawing constructor
Cartoon constructor</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can see that the construction happens
from the base &#8220;outward,&#8221; so the base class is initialized before the
derived-class constructors can access it.

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

<backtalk:display ID=TIJ3_CHAPTER6_I25>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Even if you don&#8217;t create a
constructor for <B>Cartoon(&#160;)</B>, the compiler will
<A NAME="Index574"></A>synthesize a default constructor for you that calls the
base class constructor. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I25' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I26>
</FONT><BR></P></DIV>
<A NAME="Heading210"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Constructors with arguments</H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The above example has default
<A NAME="Index575"></A>constructors; that is, they don&#8217;t have any
arguments. It&#8217;s easy for the compiler to call these because there&#8217;s
no question about what arguments to pass. If your class doesn&#8217;t have
default arguments, or if you want to call a base-class constructor that has an
argument, you must explicitly write the calls to the base-class constructor
using the <A NAME="Index576"></A><B>super</B> keyword and the appropriate
argument list:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c06:Chess.java</font>
<font color=#009900>// Inheritance, constructors and arguments.</font>

<font color=#0000ff>class</font> Game {
  Game(<font color=#0000ff>int</font> i) {
    System.out.println(<font color=#004488>"Game constructor"</font>);
  }
}

<font color=#0000ff>class</font> BoardGame <font color=#0000ff>extends</font> Game {
  BoardGame(<font color=#0000ff>int</font> i) {
    <font color=#0000ff>super</font>(i);
    System.out.println(<font color=#004488>"BoardGame constructor"</font>);
  }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Chess <font color=#0000ff>extends</font> BoardGame {
  Chess() {
    <font color=#0000ff>super</font>(11);
    System.out.println(<font color=#004488>"Chess constructor"</font>);
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Chess x = <font color=#0000ff>new</font> Chess();
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you don&#8217;t call the base-class
constructor in <B>BoardGame(&#160;)</B>, the compiler will complain that it
can&#8217;t find a constructor of the form <B>Game(&#160;)</B>. In addition, the
call to the base-class constructor <I>must</I> be the first thing you do in the
derived-class constructor. (The compiler will remind you if you get it wrong.)

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

<backtalk:display ID=TIJ3_CHAPTER6_I27>
</FONT><BR></P></DIV>
<A NAME="Heading211"></A><FONT FACE = "Verdana"><H4 ALIGN="LEFT">
Catching base constructor
exceptions<BR><A NAME="Index577"></A><A NAME="Index578"></A><A NAME="Index579"></A></H4></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">As just noted, the compiler forces you to
place the base-class constructor call first in the body of the derived-class
constructor. This means nothing else can appear before it. As you&#8217;ll see
in Chapter 10, this also prevents a derived-class constructor from catching any
exceptions that come from a base class. This can be inconvenient at times.

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

<backtalk:display ID=TIJ3_CHAPTER6_I28>
</FONT><A NAME="_Toc305593254"></A><A NAME="_Toc305628726"></A><A NAME="_Toc312374019"></A><A NAME="_Toc375545309"></A><A NAME="_Toc481064607"></A><BR></P></DIV>
<A NAME="Heading212"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Combining composition <BR>and
inheritance<BR><A NAME="Index580"></A><A NAME="Index581"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It is very common to use composition and
inheritance together. The following example shows the creation of a more complex
class, using both inheritance and composition, along with the necessary
<A NAME="Index582"></A><A NAME="Index583"></A>constructor
initialization:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c06:PlaceSetting.java</font>
<font color=#009900>// Combining composition &amp; inheritance.</font>

<font color=#0000ff>class</font> Plate {
  Plate(<font color=#0000ff>int</font> i) {
    System.out.println(<font color=#004488>"Plate constructor"</font>);
  }
}

<font color=#0000ff>class</font> DinnerPlate <font color=#0000ff>extends</font> Plate {
  DinnerPlate(<font color=#0000ff>int</font> i) {
    <font color=#0000ff>super</font>(i);
    System.out.println(
      <font color=#004488>"DinnerPlate constructor"</font>);
  }
}

<font color=#0000ff>class</font> Utensil {
  Utensil(<font color=#0000ff>int</font> i) {
    System.out.println(<font color=#004488>"Utensil constructor"</font>);
  }
}

<font color=#0000ff>class</font> Spoon <font color=#0000ff>extends</font> Utensil {
  Spoon(<font color=#0000ff>int</font> i) {
    <font color=#0000ff>super</font>(i);
    System.out.println(<font color=#004488>"Spoon constructor"</font>);
  }
}

<font color=#0000ff>class</font> Fork <font color=#0000ff>extends</font> Utensil {
  Fork(<font color=#0000ff>int</font> i) {
    <font color=#0000ff>super</font>(i);
    System.out.println(<font color=#004488>"Fork constructor"</font>);
  }
}

<font color=#0000ff>class</font> Knife <font color=#0000ff>extends</font> Utensil {
  Knife(<font color=#0000ff>int</font> i) {
    <font color=#0000ff>super</font>(i);
    System.out.println(<font color=#004488>"Knife constructor"</font>);
  }
}

<font color=#009900>// A cultural way of doing something:</font>
<font color=#0000ff>class</font> Custom {
  Custom(<font color=#0000ff>int</font> i) {
    System.out.println(<font color=#004488>"Custom constructor"</font>);
  }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> PlaceSetting <font color=#0000ff>extends</font> Custom {
  Spoon sp;
  Fork frk;
  Knife kn;
  DinnerPlate pl;
  PlaceSetting(<font color=#0000ff>int</font> i) {
    <font color=#0000ff>super</font>(i + 1);
    sp = <font color=#0000ff>new</font> Spoon(i + 2);
    frk = <font color=#0000ff>new</font> Fork(i + 3);
    kn = <font color=#0000ff>new</font> Knife(i + 4);
    pl = <font color=#0000ff>new</font> DinnerPlate(i + 5);
    System.out.println(
      <font color=#004488>"PlaceSetting constructor"</font>);
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    PlaceSetting x = <font color=#0000ff>new</font> PlaceSetting(9);
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">While the compiler forces you to
initialize the base classes, and requires that you do it right at the beginning
of the constructor, it doesn&#8217;t watch over you to make sure that you
initialize the member objects, so you must remember to pay attention to that.

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

<backtalk:display ID=TIJ3_CHAPTER6_I29>
</FONT><A NAME="_Toc375545310"></A><A NAME="_Toc481064608"></A><BR></P></DIV>
<A NAME="Heading213"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Guaranteeing proper cleanup</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Java doesn&#8217;t have the C++ concept
of a <A NAME="Index584"></A><I>destructor</I>, a method that is automatically
called when an object is destroyed. The reason is probably that in Java the
practice is simply to forget about objects rather than to destroy them, allowing
the <A NAME="Index585"></A><A NAME="Index586"></A>garbage collector to reclaim
the memory as necessary. 
</backtalk:display>
[&nbsp;<a href='http://www.mindview.net/backtalk/CommentServlet?ID=TIJ3_CHAPTER6_I29' 
  target="_blank">Add&nbsp;Comment</a>&nbsp;]

<backtalk:display ID=TIJ3_CHAPTER6_I30>
</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Often this is fine, but there are times

⌨️ 快捷键说明

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