From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001
From: Sven Eisenhauer
+In den vorigen Abschnitten wurde gezeigt, dass es viele Gemeinsamkeiten
+zwischen (abstrakten) Klassen und Interfaces gibt. Während der
+Designphase eines komplexen Softwaresystems ist es daher häufig
+schwierig, sich für eine von beiden Varianten zu entscheiden.
+Für die Verwendung des Interfaces spricht die größere
+Flexibilität durch die Möglichkeit, in unterschiedlichen
+Klassenhierarchien verwendet zu werden. Für die Verwendung einer
+Klasse spricht die Möglichkeit, bereits ausformulierbare Teile
+der Implementation zu realisieren und die Fähigkeit, statische
+Bestandteile und Konstruktoren unterzubringen.
+
+
+Wir wollen in diesem Abschnitt zeigen, wie sich beide Ansätze
+vereinen lassen. Dabei wird zunächst jeweils ein Interface zur
+Verfügung gestellt und seine Anwendung dann unter Verwendung
+einer Hilfsklasse vereinfacht.
+
+
+
+
+
+Wird ein Interface erstellt, das voraussichtlich häufig implementiert
+werden muss und/oder viele Methoden definiert, ist es sinnvoll, eine
+Default-Implementierung zur Verfü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ät.
+
+
+Als Beispiel soll ein Interface SimpleTreeNode
+definiert werden, das zur Konstruktion eines Baums verwendet werden
+kann, dessen Knoten von beliebigem Typ sind und jeweils beliebig viele
+Kinder haben:
+
+
+
+
+
+
+ Titel
+ Inhalt
+ Suchen
+ Index
+ DOC
+ Handbuch der Java-Programmierung, 5. Auflage
+
+ <<
+ <
+ >
+ >>
+ API
+ Kapitel 9 - OOP III: Interfaces
+
+
+
+
+
+9.5 Interfaces und Hilfsklassen
+
+
+
+
+9.5.1 Die Default-Implementierung
+
+
+
+
+Listing 9.16: Das SimpleTreeNode-Interface
+
+
+
+
+
+001 /* SimpleTreeNode.java */
+002
+003 public interface SimpleTreeNode
+004 {
+005 public void addChild(SimpleTreeNode child);
+006 public int getChildCnt();
+007 public SimpleTreeNode getChild(int pos);
+008 }
+
+
+SimpleTreeNode.java
+
+Die Default-Implementierung könnte wie folgt realisiert werden: + + +
+
+
+
+001 /* DefaultTreeNode.java */
+002
+003 public class DefaultTreeNode
+004 implements SimpleTreeNode
+005 {
+006 private int CAPACITY;
+007 private String name;
+008 private SimpleTreeNode[] childs;
+009 private int childcnt;
+010
+011 public DefaultTreeNode(String name)
+012 {
+013 this.CAPACITY = 5;
+014 this.name = name;
+015 this.childs = new SimpleTreeNode[CAPACITY];
+016 this.childcnt = 0;
+017 }
+018
+019 public void addChild(SimpleTreeNode child)
+020 {
+021 if (childcnt >= CAPACITY) {
+022 CAPACITY *= 2;
+023 SimpleTreeNode[] newchilds = new SimpleTreeNode[CAPACITY];
+024 for (int i = 0; i < childcnt; ++i) {
+025 newchilds[i] = childs[i];
+026 }
+027 childs = newchilds;
+028 }
+029 childs[childcnt++] = child;
+030 }
+031
+032 public int getChildCnt()
+033 {
+034 return childcnt;
+035 }
+036
+037 public SimpleTreeNode getChild(int pos)
+038 {
+039 return childs[pos];
+040 }
+041
+042 public String toString()
+043 {
+044 return name;
+045 }
+046 }
+
+ |
++DefaultTreeNode.java | +
+
![]() |
+
+
+ +Der Vorteil ist hier noch nicht sehr offensichtlich, weil die Implementierung +nicht sehr aufwändig ist. Bei komplexeren Interfaces zahlt es +sich in der Praxis meistens aus, wenn eine Default-Implementierung +zur Verfügung gestellt wird. Neben der dadurch erzielten Arbeitsersparnis +nützt sie auch zur Dokumentation und stellt eine Referenzimplementierung +des Interfaces dar. |
+
+
|
+![]() |
+
+Läßt sich eine potentielle SimpleTreeNode-Klasse +nicht von DefaultTreeNode ableiten, +muss sie das Interface selbst implementieren. Besitzt die Default-Implementierung +bereits nennenswerte Funktionalitäten, wäre es schlechter +Stil (und auch sehr fehlerträchtig), diese ein zweites Mal zu +implementieren. Statt dessen ist es eventuell möglich, die Implementierung +an die bereits vorhandene DefaultTreeNode +zu delegieren. + +
+Dazu muss die zu implementierende Klasse eine Membervariable vom Typ +DefaultTreeNode anlegen und +alle Aufrufe der Interface-Methoden an dieses Objekt weiterleiten. +Soll beispielsweise die Klasse Auto +aus Listing 7.1 in eine SimpleTreeNode +verwandelt werden, könnte die Implementierung durch Delegation +wie folgt vereinfacht werden: + + +
+
+
+
+001 /* Auto5.java */
+002
+003 public class Auto5
+004 implements SimpleTreeNode
+005 {
+006 public String name;
+007 public int erstzulassung;
+008 public int leistung;
+009
+010 private SimpleTreeNode treenode = new DefaultTreeNode("");
+011
+012 public void addChild(SimpleTreeNode child)
+013 {
+014 treenode.addChild(child);
+015 }
+016
+017 public int getChildCnt()
+018 {
+019 return treenode.getChildCnt();
+020 }
+021
+022 public SimpleTreeNode getChild(int pos)
+023 {
+024 return treenode.getChild(pos);
+025 }
+026
+027 public String toString()
+028 {
+029 return name;
+030 }
+031 }
+
+ |
++Auto5.java | +
+Hier nutzt die Klasse Auto5 +die Funktionalitäten der Membervariable DefaultTreeNode +zur Verwaltung von Unterknoten und leitet alle entsprechenden Methodenaufrufe +an sie weiter. Die Verwaltung des Knotennamens erfolgt dagegen mit +Hilfe der eigenen Membervariable name. + + + + +
+Mitunter wird ein Interface entworfen, bei dem nicht immer alle definierten +Methoden benötigt werden. In der Java-Klassenbibliothek gibt +es dafür einige Beispiele, etwa bei Listenern (siehe Kapitel 28) +oder im Collection-API (siehe Kapitel 15). +Da bei der Implementierung aber immer alle definierten Methoden implementiert +werden müssen, wenn die Klasse nicht abstrakt bleiben soll, kann +es nützlich sein, eine leere Standard-Implementierung +zur Verfügung zu stellen. Implementierende Klassen können +sich dann gegebenenfalls von dieser ableiten und brauchen nur noch +die Methoden zu realisieren, die tatsächlich benötigt werden. +
| Titel + | Inhalt + | Suchen + | Index + | DOC + | Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 + |
| << + | < + | > + | >> + | API + | © 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de + |