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

📄 chapter06.html

📁 java 是一个很好的网络开发环境。由于它是通过解释的方法
💻 HTML
📖 第 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();
    b.print();
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Note that in the <B>Bath
</B>constructor a statement is executed before any of the initializations take
place. When you don&#8217;t initialize at the point of definition, there&#8217;s
still no guarantee that you&#8217;ll perform any initialization before you send
a message to an object handle &#8211; except for the inevitable run-time
exception.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here&#8217;s the output for the
program:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Inside Bath()
Soap()
s1 = Happy
s2 = Happy
s3 = Joy
s4 = Joy
i = 47
toy = 3.14
castille = Constructed</PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When <B>print(&#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><A NAME="_Toc305593252"></A><A NAME="_Toc305628724"></A><A NAME="_Toc312374015"></A><A NAME="_Toc375545307"></A><A NAME="_Toc408018510"></A><BR></P></DIV>
<A NAME="Heading181"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Inheritance syntax<BR><A NAME="Index433"></A></H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Inheritance is such an integral
part of Java (and OOP languages in general) that it was introduced in Chapter 1
and has been used occasionally in chapters before this one because certain
situations required it. In addition, you&#8217;re always doing inheritance when
you create a class, because if you don&#8217;t say otherwise you inherit from
Java&#8217;s standard root class <B>Object</B>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The syntax for composition is
obvious, but to perform inheritance there&#8217;s a distinctly different form.
When you inherit, you say &#8220;This new class is like that old class.&#8221;
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 <A NAME="Index434"></A>keyword
<B>extends</B> followed by the name of the
<A NAME="Index435"></A><A NAME="Index436"></A><I>base class</I>. When you do
this, you automatically get all the data members and methods in the base class.
Here&#8217;s an example:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: Detergent.java</font>
<font color=#009900>// Inheritance syntax &amp; properties</font>

<font color=#0000ff>class</font> Cleanser {
  <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> <font color=#0000ff>void</font> print() { System.out.println(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();
    x.print();
  }
}

<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();
    x.print();
    System.out.println(<font color=#004488>"Testing base class:"</font>);
    Cleanser.main(args);
  }
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">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 &#8216;<B>+</B>&#8217;) that the Java
designers &#8220;overloaded&#8221; to work with
<A NAME="Index437"></A><A NAME="Index438"></A><A NAME="Index439"></A><B>String</B>s.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Second, both <B>Cleanser</B> and
<B>Detergent</B> contain a <A NAME="Index440"></A><B>main(&#160;)</B> method.
You can create a <B>main(&#160;)</B> for each one of your classes, and
it&#8217;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 <B>public</B> class invoked on the command line will
be called. (And you can have only one <B>public</B> class per file.) 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
<A NAME="Index441"></A><A NAME="Index442"></A>unit testing for each class. And
you don&#8217;t need to remove the <B>main(&#160;)</B> when you&#8217;re
finished testing; you can leave it in for later testing.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here, you can see that
<B>Detergent.main(&#160;)</B> calls <B>Cleanser.main(&#160;)</B>
explicitly.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">It&#8217;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 &#8220;friendly,&#8221; which allows
access only to package members. Thus, within this package, 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 <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>protected </B>members also allow access by derived
classes; you&#8217;ll learn about this later.) Of course, in particular cases
you must make adjustments, but this is a useful guideline.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">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>print(&#160;)</B>. Because
<B>Detergent</B> is <I>derived from</I> <B>Cleanser</B> (via the
<A NAME="Index443"></A><B>extends</B> keyword) it automatically gets all these
methods in its interface, even though you don&#8217;t see them all explicitly
defined in <B>Detergent</B>. You can think of inheritance, then, as <I>reusing
the interface.</I> (The implementation comes along for free, but that part
isn&#8217;t the primary point.)</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">As seen in <B>scrub(&#160;)</B>,
it&#8217;s possible to take a method that&#8217;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&#8217;t what you want. To solve this problem Java has the
<A NAME="Index444"></A>keyword <B>super</B> that refers to the
&#8220;<A NAME="Index445"></A>superclass&#8221; that the current class has been
inherited from. Thus the expression <B>super.scrub(&#160;)</B> calls the
base-class version of the method <B>scrub(&#160;)</B>.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When inheriting you&#8217;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 <B>extends </B>keyword suggests that you are going to add new methods to
the base-class interface, and the method <B>foam(&#160;)</B> is an example of
this.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">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><A NAME="_Toc375545308"></A><A NAME="_Toc408018511"></A><BR></P></DIV>
<A NAME="Heading182"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
Initializing the base
class<BR><A NAME="Index446"></A><A NAME="Index447"></A><A NAME="Index448"></A></H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Since there are now two classes
involved &#8211; the base class and the
<A NAME="Index449"></A><A NAME="Index450"></A>derived class &#8211; 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="Index451"></A><A NAME="Index452"></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.</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>//: 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.</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="Index453"></A>synthesize a default constructor for you that calls the
base class constructor.</FONT><BR></P></DIV>
<A NAME="Heading183"></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="Index454"></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="Index455"></A><B>super</B> keyword and the appropriate argument
list:</FONT><BR></P></DIV>

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

⌨️ 快捷键说明

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