epubjs
Version:
Render ePub documents in the browser, across many devices
65 lines (64 loc) • 7.32 kB
HTML
<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>