📄 tij0065.html
字号:
<html><body>
<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0064.html">Prev</a> | <a href="tij0066.html">Next</a>
</td>
</tr></table>
<hr>
<H2 ALIGN=LEFT>
Inheritance
syntax
<P><A NAME="Index433"></A></H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">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’re always
doing inheritance when you create a class, because if you don’t say
otherwise you inherit from Java’s standard root class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Object</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
syntax for composition is obvious, but to perform inheritance there’s a
distinctly different form. When you inherit, you say “This new class is
like that old class.” 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
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>extends</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
followed by the name of the <A NAME="Index435"></A><A NAME="Index436"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>base
class
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
When you do this, you automatically get all the data members and methods in the
base class. Here’s an example:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Detergent.java</font>
<font color="#009900">// Inheritance syntax & properties</font>
<font color="#0000ff">class</font> Cleanser {
<font color="#0000ff">private</font> String s = <font color="#0000ff">new</font> String("Cleanser");
<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(" dilute()"); }
<font color="#0000ff">public</font> <font color="#0000ff">void</font> apply() { append(" apply()"); }
<font color="#0000ff">public</font> <font color="#0000ff">void</font> scrub() { append(" scrub()"); }
<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(" Detergent.scrub()");
<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(" foam()"); }
<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("Testing base <font color="#0000ff">class</font>:");
Cleanser.main(args);
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
demonstrates a number of features. First, in the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cleanser</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>append( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s
are concatenated to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>s</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
using the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>+=</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
operator, which is one of the operators (along with ‘
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>+</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">’)
that the Java designers “overloaded” to work with <A NAME="Index437"></A><A NAME="Index438"></A><A NAME="Index439"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>String</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Second,
both
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cleanser</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Detergent</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
contain a <A NAME="Index440"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method. You can create a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for each one of your classes, and it’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
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class invoked on the command line will be called. (And you can have only one
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class per file.) So in this case, when you say
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>java
Detergent
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Detergent.main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
will be called. But you can also say
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>java
Cleanser
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">to
invoke
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cleanser.main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
even though
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cleanser</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is not a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class. This technique of putting a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in each class allows easy <A NAME="Index441"></A><A NAME="Index442"></A>unit
testing for each class. And you don’t need to remove the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
when you’re finished testing; you can leave it in for later testing.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Here,
you can see that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Detergent.main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
calls
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cleanser.main( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
explicitly.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It’s
important that all of the methods in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cleanser
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">are
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Remember that if you leave off any access specifier the member defaults to
“friendly,” which allows access only to package members. Thus,
within this package, anyone could use those methods if there were no access
specifier.
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Detergent</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
would have no trouble, for example. However, if a class from some other package
were to inherit
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cleanser</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
it could access only
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">members.
So to plan for inheritance, as a general rule make all fields
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>private
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">and
all methods
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public.
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>protected
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">members
also allow access by derived classes; you’ll learn about this later.) Of
course, in particular cases you must make adjustments, but this is a useful
guideline.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Note
that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cleanser</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
has a set of methods in its interface:
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>append( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>dilute( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>apply( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>scrub( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>print( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Because
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Detergent</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>derived
from
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cleanser</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(via the <A NAME="Index443"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>extends</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword) it automatically gets all these methods in its interface, even though
you don’t see them all explicitly defined in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Detergent</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
You can think of inheritance, then, as
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -