📄 tij0080.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="tij0079.html">Prev</a> | <a href="tij0081.html">Next</a>
</td>
</tr></table>
<hr>
<H2 ALIGN=LEFT>
Interfaces</H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
<A NAME="Index588"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword takes the abstract
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">concept
one step further. You could think of it as a “pure” abstract
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">class.
It allows the creator to establish the form for a class: method names, argument
lists and return types, but no method bodies. An
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
can also contain data members of primitive types, but these are implicitly <A NAME="Index589"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and <A NAME="Index590"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>final</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
An
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
provides only a form, but no <A NAME="Index591"></A>implementation.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">An
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
says: “This is what all classes that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>implement</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
this particular interface will look like.” Thus, any code that uses a
particular
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
knows what methods might be called for that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and that’s all. So the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is used to establish a “protocol” between classes. (Some
object-oriented programming languages have a keyword called <A NAME="Index592"></A><A NAME="Index593"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>protocol</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to do the same thing.)
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">To
create an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
use the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword instead of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>class</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword. Like a class, you can add the <A NAME="Index594"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword before the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">keyword
(but only if that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is defined in a file of the same name) or leave it off to give “<A NAME="Index595"></A>friendly”
status.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">To
make a class that conforms to a particular
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(or group of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s)
use the <A NAME="Index596"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>implements</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword. You’re saying “The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is what it looks like and here’s how it
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>works</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.”
Other than that, it bears a strong resemblance to inheritance. The diagram for
the instrument example shows this:
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Once
you’ve implemented an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
that implementation becomes an ordinary class that can be extended in the
regular way.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can choose to explicitly declare the method declarations in an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
But they are
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
even if you don’t say it. So when you
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>implement</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
the methods from the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
must be defined as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public.</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
Otherwise they would default to “friendly” and you’d be
restricting the accessibility of a method during inheritance, which is not
allowed by the Java compiler.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see this in the modified version of the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Instrument</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
example. Note that every method in the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is strictly a declaration, which is the only thing the compiler allows. In
addition, none of the methods in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Instrument5</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are declared as
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
but they’re automatically
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
anyway:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Music5.java</font>
<font color="#009900">// Interfaces</font>
<font color="#0000ff">import</font> java.util.*;
<font color="#0000ff">interface</font> Instrument5 {
<font color="#009900">// Compile-time constant:</font>
<font color="#0000ff">int</font> i = 5; <font color="#009900">// static & final</font>
<font color="#009900">// Cannot have method definitions:</font>
<font color="#0000ff">void</font> play(); <font color="#009900">// Automatically public</font>
String what();
<font color="#0000ff">void</font> adjust();
}
<font color="#0000ff">class</font> Wind5 <font color="#0000ff">implements</font> Instrument5 {
<font color="#0000ff">public</font> <font color="#0000ff">void</font> play() {
System.out.println("Wind5.play()");
}
<font color="#0000ff">public</font> String what() { <font color="#0000ff">return</font> "Wind5"; }
<font color="#0000ff">public</font> <font color="#0000ff">void</font> adjust() {}
}
<font color="#0000ff">class</font> Percussion5 <font color="#0000ff">implements</font> Instrument5 {
<font color="#0000ff">public</font> <font color="#0000ff">void</font> play() {
System.out.println("Percussion5.play()");
}
<font color="#0000ff">public</font> String what() { <font color="#0000ff">return</font> "Percussion5"; }
<font color="#0000ff">public</font> <font color="#0000ff">void</font> adjust() {}
}
<font color="#0000ff">class</font> Stringed5 <font color="#0000ff">implements</font> Instrument5 {
<font color="#0000ff">public</font> <font color="#0000ff">void</font> play() {
System.out.println("Stringed5.play()");
}
<font color="#0000ff">public</font> String what() { <font color="#0000ff">return</font> "Stringed5"; }
<font color="#0000ff">public</font> <font color="#0000ff">void</font> adjust() {}
}
<font color="#0000ff">class</font> Brass5 <font color="#0000ff">extends</font> Wind5 {
<font color="#0000ff">public</font> <font color="#0000ff">void</font> play() {
System.out.println("Brass5.play()");
}
<font color="#0000ff">public</font> <font color="#0000ff">void</font> adjust() {
System.out.println("Brass5.adjust()");
}
}
<font color="#0000ff">class</font> Woodwind5 <font color="#0000ff">extends</font> Wind5 {
<font color="#0000ff">public</font> <font color="#0000ff">void</font> play() {
System.out.println("Woodwind5.play()");
}
<font color="#0000ff">public</font> String what() { <font color="#0000ff">return</font> "Woodwind5"; }
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Music5 {
<font color="#009900">// Doesn't care about type, so new types</font>
<font color="#009900">// added to the system still work right:</font>
<font color="#0000ff">static</font> <font color="#0000ff">void</font> tune(Instrument5 i) {
<font color="#009900">// ...</font>
i.play();
}
<font color="#0000ff">static</font> <font color="#0000ff">void</font> tuneAll(Instrument5[] e) {
<font color="#0000ff">for</font>(<font color="#0000ff">int</font> i = 0; i < e.length; i++)
tune(e[i]);
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Instrument5[] orchestra = <font color="#0000ff">new</font> Instrument5[5];
<font color="#0000ff">int</font> i = 0;
<font color="#009900">// Upcasting during addition to the array:</font>
orchestra[i++] = <font color="#0000ff">new</font> Wind5();
orchestra[i++] = <font color="#0000ff">new</font> Percussion5();
orchestra[i++] = <font color="#0000ff">new</font> Stringed5();
orchestra[i++] = <font color="#0000ff">new</font> Brass5();
orchestra[i++] = <font color="#0000ff">new</font> Woodwind5();
tuneAll(orchestra);
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
rest of the code works the same. It doesn’t matter if you are <A NAME="Index597"></A>upcasting
to a “regular” class called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Instrument5</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Instrument5</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
or to an <A NAME="Index598"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Instrument5</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The behavior is the same. In fact, you can see in the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>tune( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method that there isn’t any evidence about whether
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Instrument5</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is a “regular” class, an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class or an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This is the intent: Each approach gives the programmer different control over
the way objects are created and used.
</FONT><a name="_Toc375545336"></a><a name="_Toc408018539"></a><P></DIV>
<A NAME="Heading217"></A><H3 ALIGN=LEFT>
“Multiple
inheritance” in Java
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
isn’t simply a “more pure” form of
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>abstract</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class. It has a higher purpose than that. Because an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
has no implementation at all – that is, there is no storage associated
with an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>interface
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">–</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -