UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

212 lines (200 loc) 23.9 kB
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <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>