Folien, pdf

Werbung
Info B VL 8: Abstrakte Klassen &
Interfaces
Objektorientiere Programmierung in Java
2003
Ute Schmid (Vorlesung)
Elmar Ludwig (Übung)
FB Mathematik/Informatik, Universität Osnabrück
Info B VL 8: Abstrakte Klassen & Interfaces – p.199
Motivation: Abstrakte Klassen
Illustration: myshapes2
Implementation verschiedener Klassen für
geometrische Figuren: Circle, Rectangle, Square,
Ellipse, Triangle
Arbeiten mit einem Array von Shape-Objekten: Es
wäre günstig, wenn eine gemeinsame Oberklasse
Shape existiert, die alle Komponenten definiert, die
allen geometrischen Formen gemeinsam sind.
Was ist mit den Methoden area() und
circumference()?
(Ohne konkrete geometrische Gestalt ist
Berechnungsvorschrift unbekannt.)
abstrakte Methoden!
Info B VL 8: Abstrakte Klassen & Interfaces – p.200
Abstrakte Klassen und Methoden (1)
public abstract class Shape {
public abstract double area();
}
Abstrakte Methode: Definition ohne Implementation
(Körper); Modifikator abstract; Methodenkopf
abgeschlossen durch Semikolon.
Jede Klasse, die eine abstrakte Methode enthält, ist
selbst abstrakt und muss als abstract deklariert
werden.
Eine abstrakte Klasse kann nicht instantiiert werden
(keine Objekt-Erzeugung mit new möglich).
Eine Unterklasse einer abstrakten Klasse kann nur
instantiiert werden, wenn alle abstrakten Methoden der
Oberklasse implementiert werden.
Info B VL 8: Abstrakte Klassen & Interfaces – p.201
Abstrakte Klassen und Methoden (2)
Eine Unterklasse, die nicht alle abstrakten Methoden
implementiert, ist selbst abstrakt.
static- und final-Methoden können nicht abstrakt
sein, da diese nicht von einer Unterklasse
überschrieben werden können.
private Methoden sind implizit final. Ebenso
können final Klassen keine abstrakten Methoden
enthalten.
Klassen können abstract deklariert werden, auch
wenn sie keine abstrakten Methoden enthalten.
Hinweis, dass Methoden unvollständig sind und dass
die Methode als Oberklasse für konkrete Unterklassen
gedacht ist.
(Abstrakte Klassen können generell nicht instantiiert
werden.)
Info B VL 8: Abstrakte Klassen & Interfaces – p.202
Abstrakte Klassen und Methoden (3)
Objekte von Unterklassen können direkt (ohne Cast)
an Variablen (z. B. Elemente eines Arrays von Shapes)
der Oberklasse zugewiesen werden.
Abstrakte Methoden der Oberklasse können für jedes
Objekt einer konkreten Unterklasse aufgerufen werden
(dynamic method lookup).
Beispiel: ShapeTest.java
Info B VL 8: Abstrakte Klassen & Interfaces – p.203
Motivation: Interfaces
Nächste Erweiterung des Shapes-Beispiels: Nicht nur
Grösse, auch Position der geometrischen Objekte in
der Ebene.
Erste Idee: weitere abstrakte Klasse CenteredShape
mit Unterklassen CenteredCircle,
CenteredRectangle, ...
CenteredCircle soll natürlich auch die Methoden
von Circle erben.
Problem: Java erlaubt nicht, dass eine Klasse mehr als
eine Oberklasse hat! (Mehrfachvererbung)
Java Lösung: Interfaces (Schnittstellen)
Info B VL 8: Abstrakte Klassen & Interfaces – p.204
Interfaces (1)
public interface Centered {
public void setCenter(double x, double y);
public double getCenterX();
public double getCenterY();
}
Eine Klasse kann beliebig viele Interfaces
implementieren.
Ein Interface ist ein Referenztyp sehr ähnlich einer
Klasse:
Definiert wird eine Funktionalität und nicht eine
Implementation (Realisierung)
ein Interface gibt Signaturen – Namen und Typen
von Methoden (und Konstanten) – vor.
Info B VL 8: Abstrakte Klassen & Interfaces – p.205
Interfaces (2)
Ein Interface wird mit dem Schlüsselwort interface
deklariert.
Ein Interface enthält keinerlei
Methoden-Implementation.
Alle Methoden sind implizit abstrakt, auch wenn ohne
diesen Modifikator deklariert.
Ein Interface kann nur Instanz-Methoden enthalten.
Ein Interface ist ohne Sichtbarkeitsmodifikator
paketsichtbar. Als einziger Sichtbarkeitsmodifikator
darf public angegeben werden. Alle Methoden sind
implizit public, auch wenn der Modifikator nicht
explizit angegeben ist.
Es ist ein Fehler, protected oder private
Methoden in einem Interface zu deklarieren!
Info B VL 8: Abstrakte Klassen & Interfaces – p.206
Interfaces (3)
Ein Interface kann keine Instanz-Felder definieren,
aber als static und final deklarierte Konstanten.
Da ein Interface nicht instantiiert werden kann,
definiert es keinen Konstruktor.
Interfaces sind reine Spezifikationen!
Info B VL 8: Abstrakte Klassen & Interfaces – p.207
Unterklasse extends Oberklasse
Klasse implements Interface
Implementation eines Interfaces
Schlüsselwort implements folgt nach extends (falls
Oberklasse angegeben); wird von einem oder
mehreren (durch Komma getrennte) Namen von
Interfaces gefolgt.
implements bedeutet, dass in der
implementierenden Klasse die Körper für Methoden
des Interfaces definiert werden. Werden nicht alle
Methoden implementiert, so ist die Klasse abstrakt und
muss als solche deklariert werden. (Alle Methoden des
Interfaces werden Teil der Klasse.)
Beispielcode: CenteredRectangle.java
Info B VL 8: Abstrakte Klassen & Interfaces – p.208
Interfaces und Konstanten (1)
Konstanten dürfen in Interface-Deklarationen
vorkommen.
Alle Felder, die in einem Interface deklariert werden,
werden implizit als static und final aufgefasst,
auch wenn nicht explizit so deklariert.
Es ist jedoch guter Stil, diese Modifikatoren explizit
anzugeben!
Jede Klasse, die das Interface implementiert, erbt die
Konstanten und kann sie benutzen, als wären sie
direkt in der Klasse selbst deklariert (keine
Voranstellung des Interface-Namens vor den
Konstanten-Namen notwendig).
Info B VL 8: Abstrakte Klassen & Interfaces – p.209
Interfaces und Konstanten (2)
Konstanten müssen nicht unbedingt mit festen Werten
initialisiert werden:
public interface RandVals {
int rint = (int) (Math.random() * 10);
long rlong = (long) (Math.random() * 10);
float rfloat = (float) (Math.random() * 10);
double rdouble = Math.random() * 10;
}
Manchmal nützlich: Interface, das nur Konstanten
enthält.
Konstanten, die von mehreren Klassen benutzt werden
(wie Port-Nummern, die von Client und Server benutzt
werden).
Beispiel: java.io.ObjectStreamConstants
(Konstanten für Javas Serialisierungs-Mechanismus)
Info B VL 8: Abstrakte Klassen & Interfaces – p.210
Beispiel ‘Shapes’
Beispielcode: CShapeTest.java
Shape
instanceof
Interface/Klasse
Object
Wenn eine Klasse ein Interface implementiert, können
Objekte dieser Klasse an eine Variable vom Typ des
Interfaces zugewiesen werden.
<<interface>>
Centered
Circle
CenteredCircle
Rectangle
CenteredRectangle
Square
CenteredSquare
Info B VL 8: Abstrakte Klassen & Interfaces – p.211
Interfaces vs. Abstrakte Klassen (1)
Entwurfsentscheidung zwischen abstrakter Klasse und
Interface.
Interface: Jede Klasse kann es implementieren.
Zwei nicht verwandte Klassen können dasselbe
Interface implementieren.
Abstrakte Klasse: Nur eine Klasse kann Oberklasse
einer anderen Klasse sein.
Interface: Nur abstrakte Methoden; wenn Methoden
für viele Klassen gleich sind, so müssen sie immer neu
implementiert werden.
Abstrakte Klasse: Kann Default-Implementation für
typische Methoden liefern.
Info B VL 8: Abstrakte Klassen & Interfaces – p.212
Interfaces vs. Abstrakte Klassen (2)
Kompatibilität:
Wenn Interface zum public API hinzugefügt wird und
später das Interface um eine Methode erweitert wird,
so sind alle Klassen, die das Interface implementieren,
“kaputt”.
Zu abstrakten Klassen können implementierte
Methoden gefahrlos hinzugefügt werden.
Manchmal nützlich: Abstrakte Klasse, die ein Interface
implementiert und Default-Implementationen für
Methoden der Unterklassen liefert. (Adapter-Klasse)
Info B VL 8: Abstrakte Klassen & Interfaces – p.213
Implementation mehrerer Interf.
Wenn die Klasse, die mehrere Interfaces
implementiert, nicht abstrakt sein soll, so müssen die
Methoden aller Interfaces implementiert werden.
public class SuperDuperSquare extends Shape
implements Centered, Scalable {
// Methods omitted
}
Info B VL 8: Abstrakte Klassen & Interfaces – p.214
Erweitern von Interfaces
Wie Klassen Unterklassen haben können, so können
Interfaces Unter-Interfaces haben.
Bei Interfaces dürfen hinter extends mehrere andere
Interfaces stehen.
public interface Positionable extends Centered {
public void setUpperRightCorner(double x, double y);
public double getUpperRightX();
public double getUpperRightY();
}
public interface Transformable extends
Scalable, Translatable, Rotatable {}
public interface SuperShape extends
Positionable, Transformable {}
Info B VL 8: Abstrakte Klassen & Interfaces – p.215
Probleme
Probleme ähnlich zu Mehrfachvererbung
Regeln, wenn Methoden gleichen Namens in
verschiedenen (zu implementierenden, erweiternden)
Interfaces vorkommen:
Methoden mit gleichem Namen und gleicher
Signatur werden einmal aufgenommen.
Methoden mit gleichem Namen und verschiedenen
Signaturen sind überladen.
Methoden mit gleichem Namen, gleichen
Parametern und verschiedenem Rückgabetyp
führen zu Übersetungs-Fehler.
Bei Methoden mit gleicher Signatur und
verschiedenen spezifizierten Exceptions muss die
“Schnittmenge” dieser Exceptions oder eine
Teilmenge davon spezifiziert werden.
Info B VL 8: Abstrakte Klassen & Interfaces – p.216
Beispiel
Übersetzungsfehler:
interface X {
void setup() throws FileNotFoundException;
}
interface Y {
void setup() throws IOException;
}
// Schnittmenge ist FileNotFoundException
class Z implements X, Y {
public void setup() throws IOException {
// ...
}
}
Info B VL 8: Abstrakte Klassen & Interfaces – p.217
Marker-Interfaces
Manchmal ist es nützlich, ein leeres Interface zu
definieren.
Klasse, die dieses Interface implementiert, muss keine
Methoden implementieren.
Jede Instanz der Klasse ist zulässige “Instanz” des
Interfaces.
Prüfbar mit instanceof
Beispiel: Cloneable
MyClass o;
// Initialized elsewhere
MyClass copy;
if (o instanceof Cloneable) copy = o.clone();
else copy = null;
Info B VL 8: Abstrakte Klassen & Interfaces – p.218
Enumeration-Interface
Idee: Für eine Datenstruktur, die Elemente hält, sollen
diese Elemente aufgezählt werden.
Typisch für Collection-Klassen, in denen Objekte
gehalten werden.
Beispiele: Stack, LinkedList
Vordefiniertes Enumeration-Interface mit zwei
Methoden:
boolean hasMoreElements(): true, wenn die
Aufzählung noch weitere Elemente enthält, false
sonst
Object nextElement(): liefert das nächste
Element, falls es existiert, sonst wird eine
Exception ausgelöst.
Info B VL 8: Abstrakte Klassen & Interfaces – p.219
Beispiel
Beispielcode: ListEnumerator.java
Eine unelegante Art, den Inhalt einer Liste aufzuzählen, ist
es, mit einer Schleife über die Liste zu laufen:
MyList intlist = new MyList();
for (int i=0; i < 10; i++) {
intlist.add(new Integer(i));
}
// enumerate elements by index
for (int i=0; i < intlist.size(); i++) {
System.out.println(intlist.get(i));
besser: Implementation einer Enumeration
Info B VL 8: Abstrakte Klassen & Interfaces – p.220
Herunterladen