epubjs
Version:
Render ePub documents in the browser, across many devices
212 lines (200 loc) • 23.9 kB
HTML
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Interfaces</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Interfaces"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-6-SECT-2"/>Interfaces</h1></div></div></div><p>Java expands on the concept of abstract methods with <a id="I_indexterm6_id697155" class="indexterm"/><span class="emphasis"><em>interfaces</em></span>. It’s often desirable to
specify a group of abstract methods defining some behavior for an object
without tying it to any implementation at all. In Java, this is called an
interface. An interface defines a set of methods that a class must
implement. A class in Java can declare that it
<span class="emphasis"><em>implements</em></span> an interface if it implements the required
methods. Unlike extending an abstract class, a class implementing an
interface doesn’t have to inherit from any particular part of the
inheritance hierarchy or use a particular implementation.</p><p>Interfaces are kind of like Boy Scout or Girl Scout merit badges. A
scout who has learned to build a birdhouse can walk around wearing a
little sleeve patch with a picture of one. This says to the world, “I know
how to build a birdhouse.” Similarly, an interface is a list of methods
that define some set of behavior for an object. Any class that implements
each method listed in the interface can declare at compile time that it
implements the interface and wear, as its merit badge, an extra type—the
interface’s type.</p><p>Interface types act like class types. You can declare variables to
be of an interface type, you can declare arguments of methods to accept
interface types, and you can specify that the return type of a method is
an interface type. In each case, what is meant is that any object that
implements the interface (i.e., wears the right merit badge) can fill that
role. In this sense, interfaces are orthogonal to the class hierarchy.
They cut across the boundaries of what kind of object an item
<span class="emphasis"><em>is</em></span> and deal with it only in terms of what it can
<span class="emphasis"><em>do</em></span>. A class can implement as many interfaces as it
desires. In this way, interfaces in Java replace much of the need for
multiple inheritance in other languages (and all its messy
complications).</p><p>An interface looks, essentially, like a purely <code class="literal">abstract</code> class (i.e., a class with only <code class="literal">abstract</code> methods). You define an interface with
the <a id="I_indexterm6_id697218" class="indexterm"/><code class="literal">interface</code> keyword and
list its methods with no bodies, just prototypes (signatures):</p><a id="I_6_tt308"/><pre class="programlisting"> <code class="kd">interface</code> <code class="nc">Driveable</code> <code class="o">{</code>
<code class="kt">boolean</code> <code class="nf">startEngine</code><code class="o">();</code>
<code class="kt">void</code> <code class="nf">stopEngine</code><code class="o">();</code>
<code class="kt">float</code> <code class="nf">accelerate</code><code class="o">(</code> <code class="kt">float</code> <code class="n">acc</code> <code class="o">);</code>
<code class="kt">boolean</code> <code class="nf">turn</code><code class="o">(</code> <code class="n">Direction</code> <code class="n">dir</code> <code class="o">);</code>
<code class="o">}</code></pre><p>The previous example defines an interface called <code class="literal">Driveable</code> with four methods. It’s acceptable,
but not necessary, to declare the methods in an interface with the
<code class="literal">abstract</code> modifier; we haven’t done that
here. More importantly, the methods of an interface are always considered
<a id="I_indexterm6_id697257" class="indexterm"/><code class="literal">public</code>, and you can
optionally declare them as so. Why public? Well, the user of the interface
wouldn’t necessarily be able to see them otherwise, and interfaces are
generally intended to describe the behavior of an object, not its implementation.</p><p>Interfaces define capabilities, so it’s common to name interfaces
after their capabilities. <code class="literal">Driveable</code>,
<code class="literal">Runnable</code>, and <code class="literal">Updateable</code> are good interface names. Any class
that implements all the methods can then declare that it implements the
interface by using a special <a id="I_indexterm6_id697302" class="indexterm"/><code class="literal">implements</code> clause in its
class definition. For example:</p><a id="I_6_tt309"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Automobile</code> <code class="kd">implements</code> <code class="n">Driveable</code> <code class="o">{</code>
<code class="o">...</code>
<code class="kd">public</code> <code class="kt">boolean</code> <code class="nf">startEngine</code><code class="o">()</code> <code class="o">{</code>
<code class="k">if</code> <code class="o">(</code> <code class="n">notTooCold</code> <code class="o">)</code>
<code class="n">engineRunning</code> <code class="o">=</code> <code class="kc">true</code><code class="o">;</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">stopEngine</code><code class="o">()</code> <code class="o">{</code>
<code class="n">engineRunning</code> <code class="o">=</code> <code class="kc">false</code><code class="o">;</code>
<code class="o">}</code>
<code class="kd">public</code> <code class="kt">float</code> <code class="nf">accelerate</code><code class="o">(</code> <code class="kt">float</code> <code class="n">acc</code> <code class="o">)</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="kd">public</code> <code class="kt">boolean</code> <code class="nf">turn</code><code class="o">(</code> <code class="n">Direction</code> <code class="n">dir</code> <code class="o">)</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>Here, the class <code class="literal">Automobile</code>
implements the methods of the <code class="literal">Driveable</code>
interface and declares itself a type of <code class="literal">Driveable</code> using the <code class="literal">implements</code> keyword.</p><p>As shown in <a class="xref" href="ch06s02.html#learnjava3-CHP-6-FIG-5" title="Figure 6-5. Implementing the Driveable interface">Figure 6-5</a>, another
class, such as <code class="literal">Lawnmower</code>, can also
implement the <code class="literal">Driveable</code> interface. The
figure illustrates the <code class="literal">Driveable</code>
interface being implemented by two different classes. While it’s possible
that both <code class="literal">Automobile</code> and <code class="literal">Lawnmower</code> could derive from some primitive kind
of vehicle, they don’t have to in this scenario.</p><p>After declaring the interface, we have a new type, <code class="literal">Driveable</code>. We can declare variables of type
<code class="literal">Driveable</code> and assign them any instance
of a <code class="literal">Driveable</code> object:</p><a id="I_6_tt310"/><pre class="programlisting"> <code class="n">Automobile</code> <code class="n">auto</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Automobile</code><code class="o">();</code>
<code class="n">Lawnmower</code> <code class="n">mower</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Lawnmower</code><code class="o">();</code>
<code class="n">Driveable</code> <code class="n">vehicle</code><code class="o">;</code>
<code class="n">vehicle</code> <code class="o">=</code> <code class="n">auto</code><code class="o">;</code>
<code class="n">vehicle</code><code class="o">.</code><code class="na">startEngine</code><code class="o">();</code>
<code class="n">vehicle</code><code class="o">.</code><code class="na">stopEngine</code><code class="o">();</code>
<code class="n">vehicle</code> <code class="o">=</code> <code class="n">mower</code><code class="o">;</code>
<code class="n">vehicle</code><code class="o">.</code><code class="na">startEngine</code><code class="o">();</code>
<code class="n">vehicle</code><code class="o">.</code><code class="na">stopEngine</code><code class="o">();</code></pre><div class="figure"><a id="learnjava3-CHP-6-FIG-5"/><div class="figure-contents"><div class="mediaobject"><a id="I_6_tt311"/><img src="httpatomoreillycomsourceoreillyimages1707623.png" alt="Implementing the Driveable interface"/></div></div><p class="title">Figure 6-5. Implementing the Driveable interface</p></div><p>Both <code class="literal">Automobile</code> and <code class="literal">Lawnmower</code> implement <code class="literal">Driveable</code>, so they can be considered
interchangeable objects of that type.</p><div class="sect2" title="Interfaces as Callbacks"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-6-SECT-2.1"/>Interfaces as Callbacks</h2></div></div></div><p><a id="idx10270" class="indexterm"/> <a id="idx10285" class="indexterm"/> <a id="idx10312" class="indexterm"/>Interfaces can be used to implement “callbacks” in Java.
This is when an object effectively passes a reference to one or more of
its methods to another object. The callback occurs when the called
object subsequently invokes one of the methods. In C or C++, this is
prime territory for function pointers; Java uses interfaces instead.
More generally, this concept is extended in Java to the concept of
<span class="emphasis"><em>events</em></span> in which listener objects register with
event sources. We’ll cover events in great detail in later
chapters.</p><p>Consider two classes: a <code class="literal">TickerTape</code> class that displays data and a
<code class="literal">TextSource</code> class that provides an
information feed. We’d like our <code class="literal">TextSource</code> to send any new text data. We could
have <code class="literal">TextSource</code> store a reference to
a <code class="literal">TickerTape</code> object, but then we
could never use our <code class="literal">TextSource</code> to
send data to any other kind of object. Instead, we’d have to proliferate
subclasses of <code class="literal">TextSource</code> that dealt
with different types. A more elegant solution is to have <code class="literal">TextSource</code> store a reference to an interface
type, <code class="literal">TextReceiver</code>:</p><a id="I_6_tt313"/><pre class="programlisting"> <code class="kd">interface</code> <code class="nc">TextReceiver</code> <code class="o">{</code>
<code class="kt">void</code> <code class="nf">receiveText</code><code class="o">(</code> <code class="n">String</code> <code class="n">text</code> <code class="o">);</code>
<code class="o">}</code>
<code class="kd">class</code> <code class="nc">TickerTape</code> <code class="kd">implements</code> <code class="n">TextReceiver</code> <code class="o">{</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">receiveText</code><code class="o">(</code> <code class="n">String</code> <code class="n">text</code> <code class="o">)</code> <code class="o">{</code>
<code class="n">System</code><code class="o">.</code><code class="na">out</code><code class="o">.</code><code class="na">println</code><code class="o">(</code><code class="s">"TICKER:\n"</code> <code class="o">+</code> <code class="n">text</code> <code class="o">+</code> <code class="s">"\n"</code><code class="o">);</code>
<code class="o">}</code>
<code class="o">}</code>
<code class="kd">class</code> <code class="nc">TextSource</code> <code class="o">{</code>
<code class="n">TextReceiver</code> <code class="n">receiver</code><code class="o">;</code>
<code class="n">TextSource</code><code class="o">(</code> <code class="n">TextReceiver</code> <code class="n">r</code> <code class="o">)</code> <code class="o">{</code>
<code class="n">receiver</code> <code class="o">=</code> <code class="n">r</code><code class="o">;</code>
<code class="o">}</code>
<code class="kd">public</code> <code class="kt">void</code> <code class="nf">sendText</code><code class="o">(</code> <code class="n">String</code> <code class="n">s</code> <code class="o">)</code> <code class="o">{</code>
<code class="n">receiver</code><code class="o">.</code><code class="na">receiveText</code><code class="o">(</code> <code class="n">s</code> <code class="o">);</code>
<code class="o">}</code>
<code class="o">}</code></pre><p>The only thing <code class="literal">TextSource</code>
really cares about is finding the right method to invoke in order to
output some text. Using an interface establishes a “contract,” <code class="literal">receiveText()</code>, for that method.</p><p>When the <code class="literal">TextSource</code> is
constructed, a reference to the <code class="literal">TickerTape</code> (which implements the interface) is
stored in an instance variable. This “registers” the <code class="literal">TickerTape</code> as the <code class="literal">TextSource</code>’s “output device.” Whenever it
needs to output data, the <code class="literal">TextSource</code>
calls the output device’s <code class="literal">receiveText()</code> method. Later, we’ll see that
many APIs in Java use a model like this, but more often many “receivers”
may register with the same source.<a id="I_indexterm6_id697637" class="indexterm"/><a id="I_indexterm6_id697644" class="indexterm"/><a id="I_indexterm6_id697651" class="indexterm"/></p></div><div class="sect2" title="Interface Variables"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-6-SECT-2.2"/>Interface Variables</h2></div></div></div><p><a id="idx10284" class="indexterm"/> <a id="idx10286" class="indexterm"/> <a id="idx10313" class="indexterm"/>Although interfaces mostly allow us to specify behavior
without implementation, there’s one exception. An interface can contain
constants (<code class="literal">static final</code> variables ),
which can be referred to directly through the interface name, and which
also appear in any class that implements the interface. This feature
allows constants to be packaged for use with the methods of the
interface:</p><a id="I_6_tt314"/><pre class="programlisting"> <code class="kd">interface</code> <code class="nc">Scaleable</code> <code class="o">{</code>
<code class="kd">static</code> <code class="kd">final</code> <code class="kt">int</code> <code class="n">BIG</code> <code class="o">=</code> <code class="mi">0</code><code class="o">,</code> <code class="n">MEDIUM</code> <code class="o">=</code> <code class="mi">1</code><code class="o">,</code> <code class="n">SMALL</code> <code class="o">=</code> <code class="mi">2</code><code class="o">;</code>
<code class="kt">void</code> <code class="nf">setScale</code><code class="o">(</code> <code class="kt">int</code> <code class="n">size</code> <code class="o">);</code>
<code class="o">}</code></pre><p>The <code class="literal">Scaleable</code> interface defines
three integers: <code class="literal">BIG</code>, <code class="literal">MEDIUM</code>, and <code class="literal">SMALL</code>. All variables defined in interfaces are
implicitly <a id="I_indexterm6_id697747" class="indexterm"/><code class="literal">final</code> and <a id="I_indexterm6_id697762" class="indexterm"/><code class="literal">static</code>; you don’t need
to use the modifiers, but for clarity, we recommend that you do. A class
that implements <code class="literal">Scaleable</code> sees these
constants:</p><a id="I_6_tt315"/><pre class="programlisting"> <code class="kd">class</code> <code class="nc">Box</code> <code class="kd">implements</code> <code class="n">Scaleable</code> <code class="o">{</code>
<code class="kt">void</code> <code class="nf">setScale</code><code class="o">(</code> <code class="kt">int</code> <code class="n">size</code> <code class="o">)</code> <code class="o">{</code>
<code class="k">switch</code><code class="o">(</code> <code class="n">size</code> <code class="o">)</code> <code class="o">{</code>
<code class="k">case</code> <code class="nl">BIG:</code>
<code class="o">...</code>
<code class="k">case</code> <code class="nl">MEDIUM:</code>
<code class="o">...</code>
<code class="k">case</code> <code class="nl">SMALL:</code>
<code class="o">...</code>
<code class="o">}</code>
<code class="o">}</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>While there is nothing technically wrong with using interfaces in
this way, the main incentive for doing so disappeared when Java added
enumerations and <span class="emphasis"><em>static imports</em></span>. Using interfaces
for this purpose is bad because all those public, static constants then
appear in the public API of your class and can confuse those who use it.
What’s worse, you can’t remove them later because other code may rely on
the class that contains those values. It’s better to use an enumeration
or to put your constants in their own class and then use the new static
import syntax to remove the hassle of referring to them. We’ll discuss
static import later in this chapter. This code snippet gives a glimpse
of how it works:</p><a id="I_6_tt316"/><pre class="programlisting"> <code class="kd">enum</code> <code class="n">SizeConstants</code> <code class="o">{</code> <code class="n">BIG</code><code class="o">,</code> <code class="n">MEDIUM</code><code class="o">,</code> <code class="n">SMALL</code> <code class="o">}</code>
<code class="c1">// usage</code>
<code class="kd">static</code> <code class="kn">import</code> <code class="nn">mypackage.SizeConstants</code><code class="o">;</code>
<code class="o">...</code>
<code class="n">setSize</code><code class="o">(</code> <code class="n">MEDIUM</code> <code class="o">);</code></pre><div class="sect3" title="Flag interfaces"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-6-SECT-2.2.1"/>Flag interfaces</h3></div></div></div><p><a id="I_indexterm6_id697827" class="indexterm"/>Sometimes completely empty interfaces serve as a marker
that a class has a special property. The <a id="I_indexterm6_id697834" class="indexterm"/><code class="literal">java.io.Serializeable</code>
interface is a good example. Classes that implement <code class="literal">Serializeable</code> don’t have to add any methods
or variables. Their additional type simply identifies them to Java as
classes that want to be able to be serialized. This usage of
interfaces is less important now that Java has annotations, described
in <a class="xref" href="ch07.html" title="Chapter 7. Working with Objects and Classes">Chapter 7</a>.<a id="I_indexterm6_id697860" class="indexterm"/><a id="I_indexterm6_id697867" class="indexterm"/><a id="I_indexterm6_id697874" class="indexterm"/></p></div></div><div class="sect2" title="Subinterfaces"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-6-SECT-2.3"/>Subinterfaces</h2></div></div></div><p><a id="I_indexterm6_id697888" class="indexterm"/> <a id="idx10314" class="indexterm"/> <a id="idx10337" class="indexterm"/>An interface can extend another interface, just as a class
can extend another class. Such an interface is called a
<span class="emphasis"><em>subinterface</em></span>. For example:</p><a id="I_6_tt317"/><pre class="programlisting"> <code class="kd">interface</code> <code class="nc">DynamicallyScaleable</code> <code class="kd">extends</code> <code class="n">Scaleable</code> <code class="o">{</code>
<code class="kt">void</code> <code class="nf">changeScale</code><code class="o">(</code> <code class="kt">int</code> <code class="n">size</code> <code class="o">);</code>
<code class="o">}</code></pre><p>The interface <a id="I_indexterm6_id697937" class="indexterm"/><code class="literal">DynamicallyScaleable</code>
extends our previous <code class="literal">Scaleable</code>
interface and adds an additional method. A class that implements
<code class="literal">DynamicallyScaleable</code> must implement
all the methods of both interfaces.</p><p>Note here that we are using the term <a id="I_indexterm6_id697963" class="indexterm"/><span class="emphasis"><em>extends</em></span> and not
<span class="emphasis"><em>implements</em></span> to subtype the interface. Interfaces
can’t implement anything! But an interface is allowed to extend as many
interfaces as it wants. If you want to extend two or more interfaces,
list them after the <code class="literal">extends</code> keyword,
separated by commas:</p><a id="I_6_tt318"/><pre class="programlisting"> <code class="kd">interface</code> <code class="nc">DynamicallyScaleable</code> <code class="kd">extends</code> <code class="n">Scaleable</code><code class="o">,</code> <code class="n">SomethingElseable</code> <code class="o">{</code>
<code class="o">...</code>
<code class="o">}</code></pre><p>A class that implements this interface must also implement the
other interfaces. Furthermore, interface subtypes are assignable to
their supertypes in the same way that classes are, so an instance of
<code class="literal">DynamicallyScaleable</code> can be assigned
to a variable of type <code class="literal">Scaleable</code>, as
you might expect.</p><div class="sect3" title="Overlapping and conflicting methods"><div class="titlepage"><div><div><h3 class="title"><a id="learnjava3-CHP-6-SECT-2.3.1"/>Overlapping and conflicting methods</h3></div></div></div><p>We should also note the possibility that when an interface
extends two or more interfaces (or when a class implements two or more
interfaces), there may be overlapping or conflicting methods in those
interfaces. If two methods in different interfaces have exactly the
same signature and return type, there is no problem and the
implementation in the class satisfies both interfaces. If the methods
differ in the way that overloaded methods do, the class must implement
both method signatures. If the methods have the same name but differ
in return or exception types, the class cannot implement both and
compile-time errors occur.<a id="I_indexterm6_id698026" class="indexterm"/><a id="I_indexterm6_id698033" class="indexterm"/></p></div></div></div></body></html>