Typeinschränkungen
Wenn wir einen parametrischen Typ, wie zum Beispiel List<E>
definieren, dann dürfen wir anstelle des Typparameters E
einen beliebigen (Referenz-)Typ einsetzen.
Da E
für einen beliebigen Typ steht, können wir nichts über den Typ annehmen, ausser, dass er ein Subtyp von Object
ist.
Dies wissen wir, da alle Referenztypen in Java von Object
erben.
Manchmal möchten wir den Typ möglichst parametrisch halten, aber gleichzeit auch etwas mehr über den Typ annehmen dürfen.
Als Beispiel schauen wir uns eine Klasse OrderedTuple
an.
Dies soll zwei Werte so speichern, dass immer das erste Element das kleinere ist.
So eine Klasse macht für viele Typen wie zum Beispiel Int
, Double
, Long
und sogar String
Sinn.
Damit wir diese aber implementieren können, müssen wir entscheiden können, welches der beiden Elemente das kleinere ist.
Um dieses Problem stellt uns Java Typeinschränkungen zur Verfügung.
Wir können bei der Definition eines Typparameters mit angeben, dass dieser ein Subtyp eines anderen Typs sein muss.
Das Interface Comparable
In unserem Beispiel, muss ein konkreter Typ eine Methode unterstützen um zwei Elemente zu vergleichen.
In Java gibt es dafür das Comparable
Interface
(siehe API Doc)
welches wie folgt definiert ist:
interface Comparable<T> {
int compareTo(T other);
}
Jede Klasse, die verglichen werden kann, implementiert das Comparable
Interface.
Die Methode compareTo
wird dann so implementiert dass -1
, 0
oder +1
zurückgegeben wird.
Dabei bedeutet 0 dass other
gleich ist wie das this
Objekt.
Wenn this
kleiner ist als other
wird -1
, und wenn es grösser ist +1
zurückgegeben.
Für eine Klasse Integer
könnte die Implementation wie folgt aussehen:
class Integer implements Comparable<Integer> {
int value;
public int compareTo(Integer other) {
if (value == other.value) {
return 0;
} else if (value < other.value) {
return -1;
} else {
return 1;
}
}
}
Typeinschränkungen definieren
Um dieses Interface in der Klasse OrderedTuple
zu nutzen, können wir die Definition des parametrischen Typs wie folgt verändern:
class OrderedTuple<E extends Comparable<E>> {
E value1;
E value2;
OrderedTuple(E value1, E.value2) {
if (value1.compareTo(value2) == -1) {
this.value1 = value1;
this.value2 = value2;
} else {
this.value1 = value2;
this.value2 = value1;
}
}
}
Der Compiler prüft und garantiert nun, dass jeder Typ, der für E
eingesetzt wird, die Methode compareTo
unterstützt.
Somit dürfen wir die Methode compareTo
in der Implementation der Methoden nutzen.
Am besten Sie probieren dies auch gleich wieder selber aus.
Experimente
- Funktioniert das Programm auch noch, wenn Sie das
extends Comparable<E>
weglassen? - Kompiliert das Programm, wenn Sie statt
Integer
Tupel vonString
verwenden? - Kompiliert das Programm, wenn Sie statt
Integer
Tupel vonObject
verwenden?
Haben Sie Fragen oder Bemerkungen? Schreiben Sie diese doch ins Forum.