UNPKG

epubjs

Version:

Render ePub documents in the browser, across many devices

65 lines (64 loc) 7.32 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>Containers: Building a Better Mousetrap</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="Containers: Building a Better Mousetrap"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-8-SECT-1"/>Containers: Building a Better Mousetrap</h1></div></div></div><p><a id="idx10396" class="indexterm"/> <a id="idx10405" class="indexterm"/>In an object-oriented programming language like Java, polymorphism means that objects are always to some degree interchangeable. Any child of a type of object can serve in place of its parent type and, ultimately, every object is a child of <code class="literal">java.lang.Object</code>, the object-oriented “Eve,” so to speak. It is natural, therefore, for the most general types of <span class="emphasis"><em>containers</em></span> in Java to work with the type <code class="literal">Object</code> so that they can hold just about anything. By containers, we mean classes that hold instances of other classes in some way. The Java Collections Framework is the best example of containers. A <code class="literal">List</code>, for example, holds an ordered collection of elements of type <code class="literal">Object</code>. A <code class="literal">Map</code> holds an association of key-value pairs, with the keys and values also being of the most general type, <code class="literal">Object</code>. With a little help from wrappers for primitive types, this arrangement has served us well. But (not to get too Zen on you) in a sense, a “collection of any type” is also a “collection of no type,” and working with <code class="literal">Object</code>s pushes a great deal of responsibility onto the user of the container.</p><p>It’s kind of like a costume party for objects where everybody is wearing the same mask and disappears into the crowd of the collection. Once objects are dressed as the <code class="literal">Object</code> type, the compiler can no longer see the real types and loses track of them. It’s up to the user to pierce the anonymity of the objects later by using a type cast. And like attempting to yank off a party-goer’s fake beard, you’d better have the cast correct or you’ll get an unwelcome surprise.</p><a id="I_8_tt388"/><pre class="programlisting"> <code class="n">Date</code> <code class="n">date</code> <code class="o">=</code> <code class="k">new</code> <code class="n">Date</code><code class="o">();</code> <code class="n">List</code> <code class="n">list</code> <code class="o">=</code> <code class="k">new</code> <code class="n">ArrayList</code><code class="o">();</code> <code class="n">list</code><code class="o">.</code><code class="na">add</code><code class="o">(</code> <code class="n">date</code> <code class="o">);</code> <code class="o">...</code> <code class="n">Date</code> <code class="n">firstElement</code> <code class="o">=</code> <code class="o">(</code><code class="n">Date</code><code class="o">)</code><code class="n">list</code><code class="o">.</code><code class="na">get</code><code class="o">(</code><code class="mi">0</code><code class="o">);</code> <code class="c1">// Is the cast correct? Maybe.</code></pre><p>The <code class="literal">List</code> interface has an <code class="literal">add()</code> method that accepts any type of <code class="literal">Object</code>. Here, we assigned an instance of <code class="literal">ArrayList</code>, which is simply an implementation of the <code class="literal">List</code> interface, and added a <code class="literal">Date</code> object. Is the cast in this example correct? It depends on what happens in the elided “...” period of time.</p><div class="sect2" title="Can Containers Be Fixed?"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-8-SECT-1.1"/>Can Containers Be Fixed?</h2></div></div></div><p>It’s natural to ask if there is a way to make this situation better. What if we know that we are only going to put <code class="literal">Date</code>s into our list? Can’t we just make our own list that only accepts <code class="literal">Date</code> objects, get rid of the cast, and let the compiler help us again? The answer, surprisingly perhaps, is no. At least, not in a very satisfying way.</p><p>Our first instinct may be to try to “override” the methods of <code class="literal">ArrayList</code> in a subclass. But of course, rewriting the <code class="literal">add()</code> method in a subclass would not actually override anything; it would add a new <span class="emphasis"><em>overloaded</em></span> method.</p><a id="I_8_tt389"/><pre class="programlisting"> <code class="kd">public</code> <code class="kt">void</code> <code class="nf">add</code><code class="o">(</code> <code class="n">Object</code> <code class="n">o</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">void</code> <code class="nf">add</code><code class="o">(</code> <code class="n">Date</code> <code class="n">d</code> <code class="o">)</code> <code class="o">{</code> <code class="o">...</code> <code class="o">}</code> <code class="c1">// overloaded method</code></pre><p>The resulting object still accepts any kind of object—it just invokes different methods to get there.</p><p>Moving along, we might take on a bigger task. For example, we might write our own <code class="literal">DateList</code> class that does not extend <code class="literal">ArrayList</code>, but rather delegates the guts of its methods to the <code class="literal">ArrayList</code> implementation. With a fair amount of tedious work, that would get us an object that does everything a <code class="literal">List</code> does but that works with <code class="literal">Date</code>s. However, we’ve now shot ourselves in the foot because our container is no longer an implementation of <code class="literal">List</code> and we can’t use it interoperably with all of the utilities that deal with collections, such as <code class="literal">Collections</code>.<code class="literal">sort()</code>, or add it to another collection with the <code class="literal">Collection addAll()</code> method.</p><p>To generalize, the problem is that instead of refining the behavior of our objects, what we really want to do is to change their contract with the user. We want to adapt their API to a more specific type and polymorphism doesn’t allow that. It would seem that we are stuck with <code class="literal">Object</code>s for our collections. And this is where generics come in.<a id="I_indexterm8_id706918" class="indexterm"/><a id="I_indexterm8_id706925" class="indexterm"/></p></div></div></body></html>