📄 tij0065.html
字号:
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>reusing
the interface.
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(The implementation comes along for free, but that part isn’t the primary
point.)
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">As
seen in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>scrub( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
it’s possible to take a method that’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
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>scrub( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you cannot simply call
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>scrub( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
since that would produce a recursive call, which isn’t what you want. To
solve this problem Java has the <A NAME="Index444"></A>keyword
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that refers to the “<A NAME="Index445"></A>superclass”
that the current class has been inherited from. Thus the expression
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super.scrub( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
calls the base-class version of the method
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>scrub( )</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">When
inheriting you’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
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>extends
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">keyword
suggests that you are going to add new methods to the base-class interface, and
the method
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>foam( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is an example of this.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Detergent.main( )
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">you
can see that for a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Detergent</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object you can call all the methods that are available in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cleanser</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as well as in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Detergent
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">(i.e.
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>foam( ))</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.</FONT><a name="_Toc375545308"></a><a name="_Toc408018511"></a><P></DIV>
<A NAME="Heading183"></A><H3 ALIGN=LEFT>
Initializing
the base class
<P><A NAME="Index446"></A><A NAME="Index447"></A><A NAME="Index448"></A></H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Since
there are now two classes involved – the base class and the <A NAME="Index449"></A><A NAME="Index450"></A>derived
class – 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’t just copy the
interface of the base class. When you create an object of the derived class, it
contains within it a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>subobject</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
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’s just that, from the outside, the subobject of the base class is
wrapped within the derived-class object.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Of
course, it’s essential that the base-class subobject be initialized
correctly and there’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><P></DIV>
<font color="#990000"><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("Art constructor");
}
}
<font color="#0000ff">class</font> Drawing <font color="#0000ff">extends</font> Art {
Drawing() {
System.out.println("Drawing constructor");
}
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Cartoon <font color="#0000ff">extends</font> Drawing {
Cartoon() {
System.out.println("Cartoon constructor");
}
<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">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
output for this program shows the automatic calls:
</FONT><P></DIV>
<font color="#990000"><PRE>Art constructor
Drawing constructor
Cartoon constructor </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see that the construction happens from the base “outward,” so
the base class is initialized before the derived-class constructors can access
it.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Even
if you don’t create a constructor for
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Cartoon( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the compiler will <A NAME="Index453"></A>synthesize
a default constructor for you that calls the base class constructor.
</FONT><P></DIV>
<A NAME="Heading184"></A><H4 ALIGN=LEFT>
Constructors
with arguments
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
above example has default <A NAME="Index454"></A>constructors;
that is, they don’t have any arguments. It’s easy for the compiler
to call these because there’s no question about what arguments to pass.
If your class doesn’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></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>super</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword and the appropriate argument list:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: 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("Game constructor");
}
}
<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("BoardGame constructor");
}
}
<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("Chess constructor");
}
<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">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you don’t call the base-class constructor in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>BoardGame( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the compiler will complain that it can’t find a constructor of the form
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Game( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
In addition, the call to the base-class constructor
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>must</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
be the first thing you do in the derived-class constructor. (The compiler will
remind you if you get it wrong.)
</FONT><P></DIV>
<A NAME="Heading185"></A><H4 ALIGN=LEFT>
Catching
base constructor exceptions
<P><A NAME="Index456"></A><A NAME="Index457"></A><A NAME="Index458"></A></H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">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’ll see in Chapter 9, this also prevents a
derived-class constructor from catching any exceptions that come from a base
class. This can be inconvenient at times.
</FONT><a name="_Toc305593254"></a><a name="_Toc305628726"></a><a name="_Toc312374019"></a><a name="_Toc375545309"></a><a name="_Toc408018512"></a><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0064.html">Prev</a> | <a href="tij0066.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -