summaryrefslogtreecommitdiffstats
path: root/Master/Reference Architectures and Patterns/hjp5/html/k100062.html
blob: a3038cff9e00b6e9fe733976ff9624035a1ba4ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
<html>
<head>
<title>
Handbuch der Java-Programmierung, 5. Auflage
</title>
</head>
<body>
<a name="startofbody"></a>
<script language="JavaScript" src="hjp4lib.js">
</script>
<script language="JavaScript">
installKbdHandler("97,#startofbody;101,#endofbody;116,cover.html;122,k100003.html;115,search.html;105,index.html;100,JDKDOCS;112,APIDOCS;104,k100057.html;106,k100061.html;107,k100063.html;108,k100064.html");
</script>
<table border=0 cellpadding=0 cellspacing=1 width="100%">
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html">&nbsp;Titel&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html">&nbsp;Inhalt&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html">&nbsp;Suchen&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html">&nbsp;Index&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()">&nbsp;DOC&nbsp;</a>
<td align="right">Handbuch der Java-Programmierung, 5. Auflage
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100057.html">&nbsp;&lt;&lt;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100061.html">&nbsp;&nbsp;&lt;&nbsp;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100063.html">&nbsp;&nbsp;&gt;&nbsp;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100064.html">&nbsp;&gt;&gt;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()">&nbsp;API&nbsp;</a>
<td align="right">Kapitel 9 - OOP III: Interfaces
</table>
<hr>


<!-- Section -->
<a name="sectlevel2id009005"></a>
<h2>9.5 Interfaces und Hilfsklassen </h2>
<hr>
<ul>
<li><a href="k100062.html#sectlevel2id009005">9.5 Interfaces und Hilfsklassen</a>
<ul>
<li><a href="k100062.html#sectlevel3id009005001">9.5.1 Die Default-Implementierung</a>
<li><a href="k100062.html#sectlevel3id009005002">9.5.2 Delegation an die Default-Implementierung</a>
<li><a href="k100062.html#sectlevel3id009005003">9.5.3 Die leere Implementierung</a>
</ul>
</ul>
<hr>

<p>
In den vorigen Abschnitten wurde gezeigt, dass es viele Gemeinsamkeiten
zwischen (abstrakten) Klassen und Interfaces gibt. W&auml;hrend der
Designphase eines komplexen Softwaresystems ist es daher h&auml;ufig
schwierig, sich f&uuml;r eine von beiden Varianten zu entscheiden.
F&uuml;r die Verwendung des Interfaces spricht die gr&ouml;&szlig;ere
Flexibilit&auml;t durch die M&ouml;glichkeit, in unterschiedlichen
Klassenhierarchien verwendet zu werden. F&uuml;r die Verwendung einer
Klasse spricht die M&ouml;glichkeit, bereits ausformulierbare Teile
der Implementation zu realisieren und die F&auml;higkeit, statische
Bestandteile und Konstruktoren unterzubringen. 

<p>
Wir wollen in diesem Abschnitt zeigen, wie sich beide Ans&auml;tze
vereinen lassen. Dabei wird zun&auml;chst jeweils ein Interface zur
Verf&uuml;gung gestellt und seine Anwendung dann unter Verwendung
einer Hilfsklasse vereinfacht. 

<!-- Section -->

<a name="sectlevel3id009005001"></a>
<h3>9.5.1 Die Default-Implementierung </h3>

<p>
Wird ein Interface erstellt, das voraussichtlich h&auml;ufig implementiert
werden muss und/oder viele Methoden definiert, ist es sinnvoll, eine
<a name="ixa100570"><i>Default-Implementierung</i></a> zur Verf&uuml;gung
zu stellen. Damit ist eine Basisklasse gemeint, die das Interface
und alle sinnvoll realisierbaren Methoden implementiert. Besitzt eine
Klasse, die das Interface implementieren muss, keine andere Vaterklasse,
so kann sie von der Default-Implementierung abgeleitet werden und
erbt so bereits einen Teil der sonst manuell zu implementierenden
Funktionalit&auml;t. 

<p>
Als Beispiel soll ein Interface <font color="#000077"><tt>SimpleTreeNode</tt></font>
definiert werden, das zur Konstruktion eines Baums verwendet werden
kann, dessen Knoten von beliebigem Typ sind und jeweils beliebig viele
Kinder haben: 
<a name="listingid009016"></a>

<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
<tr>
<td valign=top>
<font color="#000055">
<pre>
<font color="#555555">001 </font><font color="#00AA00">/* SimpleTreeNode.java */</font>
<font color="#555555">002 </font>
<font color="#555555">003 </font><font color="#0000AA">public</font> <font color="#0000AA">interface</font> SimpleTreeNode
<font color="#555555">004 </font>{
<font color="#555555">005 </font>  <font color="#0000AA">public</font> <font color="#006699">void</font> addChild(SimpleTreeNode child);
<font color="#555555">006 </font>  <font color="#0000AA">public</font> <font color="#006699">int</font> getChildCnt();
<font color="#555555">007 </font>  <font color="#0000AA">public</font> SimpleTreeNode getChild(<font color="#006699">int</font> pos);
<font color="#555555">008 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/SimpleTreeNode.java"><font color="#000055" size=-1>SimpleTreeNode.java</font></a></td>
</tr>
</table>
<i>
Listing 9.16: Das SimpleTreeNode-Interface</i></p>

<p>
Die Default-Implementierung k&ouml;nnte wie folgt realisiert werden:
<a name="listingid009017"></a>

<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
<tr>
<td valign=top>
<font color="#000055">
<pre>
<font color="#555555">001 </font><font color="#00AA00">/* DefaultTreeNode.java */</font>
<font color="#555555">002 </font>
<font color="#555555">003 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> DefaultTreeNode
<font color="#555555">004 </font><font color="#0000AA">implements</font> SimpleTreeNode
<font color="#555555">005 </font>{
<font color="#555555">006 </font>  <font color="#0000AA">private</font> <font color="#006699">int</font>              CAPACITY;
<font color="#555555">007 </font>  <font color="#0000AA">private</font> String           name;
<font color="#555555">008 </font>  <font color="#0000AA">private</font> SimpleTreeNode[] childs;
<font color="#555555">009 </font>  <font color="#0000AA">private</font> <font color="#006699">int</font>              childcnt;
<font color="#555555">010 </font>
<font color="#555555">011 </font>  <font color="#0000AA">public</font> DefaultTreeNode(String name)
<font color="#555555">012 </font>  {
<font color="#555555">013 </font>    <font color="#006699">this</font>.CAPACITY = 5;
<font color="#555555">014 </font>    <font color="#006699">this</font>.name     = name;
<font color="#555555">015 </font>    <font color="#006699">this</font>.childs   = <font color="#0000AA">new</font> SimpleTreeNode[CAPACITY];
<font color="#555555">016 </font>    <font color="#006699">this</font>.childcnt = 0;
<font color="#555555">017 </font>  }
<font color="#555555">018 </font>
<font color="#555555">019 </font>  <font color="#0000AA">public</font> <font color="#006699">void</font> addChild(SimpleTreeNode child)
<font color="#555555">020 </font>  {
<font color="#555555">021 </font>    <font color="#0000AA">if</font> (childcnt &gt;= CAPACITY) {
<font color="#555555">022 </font>      CAPACITY *= 2;
<font color="#555555">023 </font>      SimpleTreeNode[] newchilds = <font color="#0000AA">new</font> SimpleTreeNode[CAPACITY];
<font color="#555555">024 </font>      <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; childcnt; ++i) {
<font color="#555555">025 </font>        newchilds[i] = childs[i];
<font color="#555555">026 </font>      }
<font color="#555555">027 </font>      childs = newchilds;
<font color="#555555">028 </font>    }
<font color="#555555">029 </font>    childs[childcnt++] = child;
<font color="#555555">030 </font>  }
<font color="#555555">031 </font>
<font color="#555555">032 </font>  <font color="#0000AA">public</font> <font color="#006699">int</font> getChildCnt()
<font color="#555555">033 </font>  {
<font color="#555555">034 </font>    <font color="#0000AA">return</font> childcnt;
<font color="#555555">035 </font>  }
<font color="#555555">036 </font>
<font color="#555555">037 </font>  <font color="#0000AA">public</font> SimpleTreeNode getChild(<font color="#006699">int</font> pos)
<font color="#555555">038 </font>  {
<font color="#555555">039 </font>    <font color="#0000AA">return</font> childs[pos];
<font color="#555555">040 </font>  }
<font color="#555555">041 </font>
<font color="#555555">042 </font>  <font color="#0000AA">public</font> String toString()
<font color="#555555">043 </font>  {
<font color="#555555">044 </font>    <font color="#0000AA">return</font> name;
<font color="#555555">045 </font>  }
<font color="#555555">046 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/DefaultTreeNode.java"><font color="#000055" size=-1>DefaultTreeNode.java</font></a></td>
</tr>
</table>
<i>
Listing 9.17: Default-Implementierung des SimpleTreeNode-Interfaces</i></p>
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>

<p>
Der Vorteil ist hier noch nicht sehr offensichtlich, weil die Implementierung
nicht sehr aufw&auml;ndig ist. Bei komplexeren Interfaces zahlt es
sich in der Praxis meistens aus, wenn eine Default-Implementierung
zur Verf&uuml;gung gestellt wird. Neben der dadurch erzielten Arbeitsersparnis
n&uuml;tzt sie auch zur Dokumentation und stellt eine Referenzimplementierung
des Interfaces dar.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#000077">
<tr>
<td><font color="#FFFFFF">&nbsp;Hinweis&nbsp;</font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#000077"><img src="trp1_1.gif"></td>
</tr>
</table>


<!-- Section -->
<a name="sectlevel3id009005002"></a>
<h3>9.5.2 <a name="ixa100571">Delegation</a> an die Default-Implementierung
</h3>

<p>
L&auml;&szlig;t sich eine potentielle <font color="#000077"><tt>SimpleTreeNode</tt></font>-Klasse
nicht von <font color="#000077"><tt>DefaultTreeNode</tt></font> ableiten,
muss sie das Interface selbst implementieren. Besitzt die Default-Implementierung
bereits nennenswerte Funktionalit&auml;ten, w&auml;re es schlechter
Stil (und auch sehr fehlertr&auml;chtig), diese ein zweites Mal zu
implementieren. Statt dessen ist es eventuell m&ouml;glich, die Implementierung
an die bereits vorhandene <font color="#000077"><tt>DefaultTreeNode</tt></font>
zu <i>delegieren</i>. 

<p>
Dazu muss die zu implementierende Klasse eine Membervariable vom Typ
<font color="#000077"><tt>DefaultTreeNode</tt></font> anlegen und
alle Aufrufe der Interface-Methoden an dieses Objekt weiterleiten.
Soll beispielsweise die Klasse <font color="#000077"><tt>Auto</tt></font>
aus <a href="k100048.html#autoklasse">Listing 7.1</a> in eine <font color="#000077"><tt>SimpleTreeNode</tt></font>
verwandelt werden, k&ouml;nnte die Implementierung durch Delegation
wie folgt vereinfacht werden: 
<a name="listingid009018"></a>

<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
<tr>
<td valign=top>
<font color="#000055">
<pre>
<font color="#555555">001 </font><font color="#00AA00">/* Auto5.java */</font>
<font color="#555555">002 </font>
<font color="#555555">003 </font><font color="#0000AA">public</font> <font color="#0000AA">class</font> Auto5
<font color="#555555">004 </font><font color="#0000AA">implements</font> SimpleTreeNode
<font color="#555555">005 </font>{
<font color="#555555">006 </font>  <font color="#0000AA">public</font> String name;
<font color="#555555">007 </font>  <font color="#0000AA">public</font> <font color="#006699">int</font>    erstzulassung;
<font color="#555555">008 </font>  <font color="#0000AA">public</font> <font color="#006699">int</font>    leistung;
<font color="#555555">009 </font>
<font color="#555555">010 </font>  <font color="#0000AA">private</font> SimpleTreeNode treenode = <font color="#0000AA">new</font> DefaultTreeNode(<font color="#0000FF">""</font>);
<font color="#555555">011 </font>
<font color="#555555">012 </font>  <font color="#0000AA">public</font> <font color="#006699">void</font> addChild(SimpleTreeNode child)
<font color="#555555">013 </font>  {
<font color="#555555">014 </font>    treenode.addChild(child);
<font color="#555555">015 </font>  }
<font color="#555555">016 </font>
<font color="#555555">017 </font>  <font color="#0000AA">public</font> <font color="#006699">int</font> getChildCnt()
<font color="#555555">018 </font>  {
<font color="#555555">019 </font>    <font color="#0000AA">return</font> treenode.getChildCnt();
<font color="#555555">020 </font>  }
<font color="#555555">021 </font>
<font color="#555555">022 </font>  <font color="#0000AA">public</font> SimpleTreeNode getChild(<font color="#006699">int</font> pos)
<font color="#555555">023 </font>  {
<font color="#555555">024 </font>    <font color="#0000AA">return</font> treenode.getChild(pos);
<font color="#555555">025 </font>  }
<font color="#555555">026 </font>
<font color="#555555">027 </font>  <font color="#0000AA">public</font> String toString()
<font color="#555555">028 </font>  {
<font color="#555555">029 </font>    <font color="#0000AA">return</font> name;
<font color="#555555">030 </font>  }
<font color="#555555">031 </font>}</pre>
</font>
</td>
<td valign=top align=right>
<a href="../examples/Auto5.java"><font color="#000055" size=-1>Auto5.java</font></a></td>
</tr>
</table>
<i>
Listing 9.18: Implementierung des SimpleTreeNode-Interfaces durch
Delegation</i></p>

<p>
Hier nutzt die Klasse <font color="#000077"><tt>Auto5</tt></font>
die Funktionalit&auml;ten der Membervariable <font color="#000077"><tt>DefaultTreeNode</tt></font>
zur Verwaltung von Unterknoten und leitet alle entsprechenden Methodenaufrufe
an sie weiter. Die Verwaltung des Knotennamens erfolgt dagegen mit
Hilfe der eigenen Membervariable <font color="#000077"><tt>name</tt></font>.


<!-- Section -->
<a name="sectlevel3id009005003"></a>
<h3>9.5.3 Die leere Implementierung </h3>

<p>
Mitunter wird ein Interface entworfen, bei dem nicht immer alle definierten
Methoden ben&ouml;tigt werden. In der Java-Klassenbibliothek gibt
es daf&uuml;r einige Beispiele, etwa bei Listenern (siehe <a href="k100180.html#kapiteleventhandling">Kapitel 28</a>)
oder im Collection-API (siehe <a href="k100097.html#kapitelcollections2">Kapitel 15</a>).
Da bei der Implementierung aber immer alle definierten Methoden implementiert
werden m&uuml;ssen, wenn die Klasse nicht abstrakt bleiben soll, kann
es n&uuml;tzlich sein, eine <i>leere</i> Standard-Implementierung
zur Verf&uuml;gung zu stellen. Implementierende Klassen k&ouml;nnen
sich dann gegebenenfalls von dieser ableiten und brauchen nur noch
die Methoden zu realisieren, die tats&auml;chlich ben&ouml;tigt werden.
<hr>
<table border=0 cellpadding=0 cellspacing=1 width="100%">
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html">&nbsp;Titel&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html">&nbsp;Inhalt&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html">&nbsp;Suchen&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html">&nbsp;Index&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()">&nbsp;DOC&nbsp;</a>
<td align="right">Handbuch der Java-Programmierung, 5. Auflage, Addison
Wesley, Version 5.0.1
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100057.html">&nbsp;&lt;&lt;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100061.html">&nbsp;&nbsp;&lt;&nbsp;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100063.html">&nbsp;&nbsp;&gt;&nbsp;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100064.html">&nbsp;&gt;&gt;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()">&nbsp;API&nbsp;</a>
<td align="right">&copy; 1998, 2007 Guido Kr&uuml;ger &amp; Thomas
Stark, <a href="http://www.javabuch.de">http://www.javabuch.de</a>
</table>
<a name="endofbody"></a>
</body>
</html>