Skip to main content

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 von String verwenden?
  • Kompiliert das Programm, wenn Sie statt Integer Tupel von Object verwenden?

Haben Sie Fragen oder Bemerkungen? Schreiben Sie diese doch ins Forum.