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

📄 tij308.htm

📁 这也是我们java老师给我们的thinking in java的一些资料
💻 HTM
📖 第 1 页 / 共 5 页
字号:
  }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Bath b = <font color=#0000ff>new</font> Bath();
    System.out.println(b);
    monitor.expect(<font color=#0000ff>new</font> String[] {
      <font color=#004488>"Inside Bath()"</font>,
      <font color=#004488>"Soap()"</font>,
      <font color=#004488>"s1 = Happy"</font>,
      <font color=#004488>"s2 = Happy"</font>,
      <font color=#004488>"s3 = Joy"</font>,
      <font color=#004488>"s4 = Joy"</font>,
      <font color=#004488>"i = 47"</font>,
      <font color=#004488>"toy = 3.14"</font>,
      <font color=#004488>"castille = Constructed"</font>
    });
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>Note that in the <b>Bath </b>constructor, a statement is executed before any of the initializations take place. When you don&#146;t initialize at the point of definition, there&#146;s still no guarantee that you&#146;ll perform any initialization before you send a message to an object reference&#151;except for the inevitable run-time exception. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_922" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>When <b>toString(&#160;)</b> is called it fills in <b>s4</b> so that all the fields are properly initialized by the time they are used. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_923" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h2>
<a name="_Toc305593252"></a><a name="_Toc305628724"></a><a name="_Toc312374015"></a><a name="_Toc375545307"></a><a name="_Toc24775636"></a><a name="Heading5161"></a>Inheritance
syntax<br></h2>
<p><a name="Index495"></a>Inheritance is an integral part of Java (and all OOP languages). It turns out that you&#146;re always doing inheritance when you create a class, because unless you explicitly inherit from some other class, you implicitly inherit from Java&#146;s standard root class <a name="Index496"></a><b>Object</b>. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_924" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>The syntax for composition is obvious, but to perform inheritance there&#146;s a distinctly different form. When you inherit, you say &#147;This new class is like that old class.&#148; You state this in code by giving the name of the class as usual, but before the opening brace of the class body, put the keyword <a name="Index497"></a><b>extends</b> followed by the name of the <a name="Index498"></a><a name="Index499"></a><i>base class</i>. When you do this, you automatically get all the fields and methods in the base class. Here&#146;s an example: <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_925" title="Send BackTalk Comment">Feedback</a></font><br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c06:Detergent.java</font>
<font color=#009900>// Inheritance syntax &amp; properties.</font>
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;

<font color=#0000ff>class</font> Cleanser {
  <font color=#0000ff>protected</font> <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
  <font color=#0000ff>private</font> String s = <font color=#0000ff>new</font> String(<font color=#004488>"Cleanser"</font>);
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> append(String a) { s += a; }
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> dilute() { append(<font color=#004488>" dilute()"</font>); }
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> apply() { append(<font color=#004488>" apply()"</font>); }
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> scrub() { append(<font color=#004488>" scrub()"</font>); }
  <font color=#0000ff>public</font> String toString() { <font color=#0000ff>return</font> s; }
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Cleanser x = <font color=#0000ff>new</font> Cleanser();
    x.dilute(); x.apply(); x.scrub();
    System.out.println(x);
    monitor.expect(<font color=#0000ff>new</font> String[] {
      <font color=#004488>"Cleanser dilute() apply() scrub()"</font>
    });
  }
}

<font color=#0000ff>public</font> <font color=#0000ff>class</font> Detergent <font color=#0000ff>extends</font> Cleanser {
  <font color=#009900>// Change a method:</font>
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> scrub() {
    append(<font color=#004488>" Detergent.scrub()"</font>);
    <font color=#0000ff>super</font>.scrub(); <font color=#009900>// Call base-class version</font>
  }
  <font color=#009900>// Add methods to the interface:</font>
  <font color=#0000ff>public</font> <font color=#0000ff>void</font> foam() { append(<font color=#004488>" foam()"</font>); }
  <font color=#009900>// Test the new class:</font>
  <font color=#0000ff>public</font> <font color=#0000ff>static</font> <font color=#0000ff>void</font> main(String[] args) {
    Detergent x = <font color=#0000ff>new</font> Detergent();
    x.dilute();
    x.apply();
    x.scrub();
    x.foam();
    System.out.println(x);
    System.out.println(<font color=#004488>"Testing base class:"</font>);
    monitor.expect(<font color=#0000ff>new</font> String[] {
      <font color=#004488>"Cleanser dilute() apply() "</font> +
      <font color=#004488>"Detergent.scrub() scrub() foam()"</font>,
      <font color=#004488>"Testing base class:"</font>,
    });
    Cleanser.main(args);
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>This demonstrates a number of features. First, in the <b>Cleanser</b> <b>append(&#160;)</b> method, <b>String</b>s are concatenated to <b>s</b> using the <b>+=</b> operator, which is one of the operators (along with &#145;<b>+</b>&#146;) that the Java designers &#147;overloaded&#148; to work with <a name="Index500"></a><a name="Index501"></a><a name="Index502"></a><b>String</b>s. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_926" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Second, both <b>Cleanser</b> and <b>Detergent</b> contain a <a name="Index503"></a><b>main(&#160;)</b> method. You can create a <b>main(&#160;)</b> for each one of your classes, and it&#146;s often recommended to code this way so that your test code is wrapped in with the class. Even if you have a lot of classes in a program, only the <b>main(&#160;)</b> for the class invoked on the command line will be called. (As long as <b>main(&#160;)</b> is <b>public</b>, it doesn&#146;t matter whether the class that it&#146;s part of is <b>public</b>.) So in this case, when you say <b>java Detergent</b>, <b>Detergent.main(&#160;)</b> will be called. But you can also say <b>java Cleanser </b>to invoke <b>Cleanser.main(&#160;)</b>, even though <b>Cleanser</b> is not a <b>public</b> class. This technique of putting a <b>main(&#160;)</b> in each class allows easy unit testing for each class. And you don&#146;t need to remove the <a name="Index504"></a><a name="Index505"></a><b>main(&#160;)</b> when you&#146;re finished testing; you can leave it in for later testing. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_927" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Here, you can see that <b>Detergent.main(&#160;)</b> calls <b>Cleanser.main(&#160;)</b> explicitly, passing it the same arguments from the command line (however, you could pass it any <b>String</b> array). <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_928" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>It&#146;s important that all of the methods in <b>Cleanser </b>are <b>public</b>. Remember that if you leave off any access specifier, the member defaults to package access, which allows access only to package members. Thus, <i>within this package</i>, anyone could use those methods if there were no access specifier. <b>Detergent</b> would have no trouble, for example. However, if a class from some other package were to inherit from <b>Cleanser</b>, it could access only <b>public </b>members. So to plan for inheritance, as a general rule make all fields <b>private </b>and all methods <b>public</b>.<b> </b>(<b>protected </b>members also allow access by derived classes; you&#146;ll learn about this later.) Of course, in particular cases you must make adjustments, but this is a useful guideline. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_929" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>Note that <b>Cleanser</b> has a set of methods in its interface: <b>append(&#160;)</b>, <b>dilute(&#160;)</b>, <b>apply(&#160;)</b>, <b>scrub(&#160;)</b>, and <b>toString(&#160;)</b>. Because <b>Detergent</b> is <i>derived from</i> <b>Cleanser</b> (via the <a name="Index506"></a><b>extends</b> keyword), it automatically gets all these methods in its interface, even though you don&#146;t see them all explicitly defined in <b>Detergent</b>. You can think of inheritance, then, as reusing the class<i>.</i> <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_930" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>As seen in <b>scrub(&#160;)</b>, it&#146;s possible to take a method that&#146;s been defined in the base class and modify it. In this case, you might want to call the method from the base class inside the new version. But inside <b>scrub(&#160;)</b>, you cannot simply call <b>scrub(&#160;)</b>, since that would produce a recursive call, which isn&#146;t what you want. To solve this problem, Java has the keyword <a name="Index507"></a><b>super</b> that refers to the &#147;superclass&#148; that the current class has been inherited from. Thus the expression <a name="Index508"></a><b>super.scrub(&#160;)</b> calls the base-class version of the method <b>scrub(&#160;)</b>. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_931" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>When inheriting you&#146;re not restricted to using the methods of the base class. You can also add new methods to the derived class exactly the way you put any method in a class: just define it. The method <b>foam(&#160;)</b> is an example of this. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_932" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p>In <b>Detergent.main(&#160;) </b>you can see that for a <b>Detergent</b> object, you can call all the methods that are available in <b>Cleanser</b> as well as in <b>Detergent </b>(i.e., <b>foam(&#160;)</b>). <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_933" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h3>
<a name="_Toc375545308"></a><a name="_Toc24775637"></a><a name="Heading5220"></a>Initializing
the base class<br></h3>
<p><a name="Index509"></a><a name="Index510"></a><a name="Index511"></a>Since there are now two classes involved&#151;the base class and the derived class&#151;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&#146;t just copy the interface of the base class. When you create an object of the derived class, it contains within it a <a name="Index512"></a><a name="Index513"></a><i>subobject</i> of the base class. This subobject is the same as if you had created an object of the base class by itself. It&#146;s just that from the outside, the subobject of the base class is wrapped within the derived-class object. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_934" title="Send BackTalk Comment">Feedback</a></font><br></p>
<p><a name="Index514"></a><a name="Index515"></a>Of course, it&#146;s essential that the base-class subobject be initialized correctly, and there&#146;s only one way to guarantee this: 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 size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_935" title="Send BackTalk Comment">Feedback</a></font><br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c06:Cartoon.java</font>
<font color=#009900>// Constructor calls during inheritance.</font>
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;

<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 {
  <font color=#0000ff>private</font> <font color=#0000ff>static</font> Test monitor = <font color=#0000ff>new</font> Test();
  <font color=#0000ff>public</font> 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();
    monitor.expect(<font color=#0000ff>new</font> String[] {
      <font color=#004488>"Art constructor"</font>,
      <font color=#004488>"Drawing constructor"</font>,
      <font color=#004488>"Cartoon constructor"</font>
    });
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE><p><br></p>
<p>You can see that the construction happens from the base &#147;outward,&#148; so the base class is initialized before the derived-class constructors can access it. Even if you don&#146;t create a constructor for <b>Cartoon(&#160;)</b>, the compiler will synthesize a default constructor for you that calls the base class constructor. <font size="-2"><a href="mailto:TIJ3@MindView.net?Subject=[TIJ3]Chap06_936" title="Send BackTalk Comment">Feedback</a></font><br></p>
<h4>
<a name="Index516"></a><a name="Heading5255"></a>Constructors with
arguments</h4>
<p>The preceding example has default constructors; that is, they don&#146;t have any arguments. It&#146;s easy for the compiler to call these because there&#146;s no question about what arguments to pass. If your class doesn&#146;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="Index517"></a><a name="Index518"></a><b>super</b> keyword and the appropriate argument list:<br></p>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: c06:Chess.java</font>
<font color=#009900>// Inheritance, constructors and arguments.</font>
<font color=#0000ff>import</font> com.bruceeckel.simpletest.*;

<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>);
  }
}

⌨️ 快捷键说明

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