Vererbung und generische Klassen

Die Vererbung zwischen generischen Klassen untereinander und mit nicht generischen Klassen ergibt eine zweidimensionale Tabelle von Möglichkeiten:

  Oberklasse generisch Oberklasse nicht generisch
Unterklasse generisch
Unterklasse nicht generisch
  • "Klassische" Vererbung

Eine generische Klasse erweitert eine generische Klasse

Will man eine generische Klasse aus einer anderen generischen Klasse ableiten so gibt es zwei Möglichkeiten:

  • der formale Typ-Parameter der Oberklasse wird weitervererbt
  • der formale Typ-Parameter der Oberklasse wird durch einen aktuellen Parameter ersetzt.

Formaler Parameter der Oberklasse ersetzt formalen Parameter der Unterklasse

 Bei dieser Form der Vererbung hat die Klassendeklaration der Unterklasse die folgende Noatation:

public class Unterklasse<T> extends Oberklasse<T>

Ein Beispiel ist die Erweiterung der zweidimensionalen Klasse Koordinate zu einer drei dimensionalen Koordinate in  der Klasse Koordinate3DGen

package s2.generics;

/**
*
* @author s@scalingbits.com
* @param <T> Generischer Typ der Klasse Koordinate
*/
public class Koordinate3DGen<T> extends Koordinate<T> {
private T z;

public T getZ() {return z;}
public void setZ(T z) {this.z = z;}

public Koordinate3DGen (T x, T y, T z) {
super (x,y);
this.z = z;
}

@Override
public String toString() {return super.toString()+", z: "+ z;}

public static void main (String[] args) {
Koordinate3DGen<Double> k1 = new Koordinate3DGen<Double>(1.1d, 2.2d, 3.3d);
System.out.println(k1);

Koordinate3DGen<Integer> k2 = new Koordinate3DGen<Integer>(1,2,3);
System.out.println(k2);
}
}

Die z Dimension kann in dieser Klasse immer nur mit dem aktuellen Parameter der beiden anderen Dimensionen instanziiert werden.

Formaler Typ-Parameter der Oberklasse wird durch aktuellen Parameter ersetzt

Eine andere Möglichkeit besteht darin den formalen Typparameter der Oberklasse durch einen aktuellen zu ersetzen und gleichzeitig einen neuen formalen Typparameter einzuführen. Hier haben die Klassendeklarationen die folgende Form:

public class Unterklasse<T> extends Oberklasse<konkrete-Klasse>

Ein Beispiel hierfür sei eine zweidimensionale Koordinate die über ein generisches Gewichtsattribut verfügt. Als aktueller Typparameter wird hier der Typ Double ausgewählt:

package s2.generics;
/**
*
* @author s@scalingbits.com
* @param <T> Die Dimensionen der Koordinate
*/
public class Koordinate2DGewicht<T> extends Koordinate<Double> {
private T gewicht;

public T getGewicht() {return gewicht;}
public void setGewicht(T g) {gewicht = g;}

public Koordinate2DGewicht (Double x, Double y, T g) {
super (x,y);
gewicht = g;
}

@Override
public String toString() {return super.toString()+", Gewicht: "+ gewicht;}

public static void main (String[] args) {
Koordinate2DGewicht<Double> k1 = new Koordinate2DGewicht<Double>(1.1d, 2.2d, 9.9d);
double dx = k1.getX();
System.out.println(k1);

Koordinate2DGewicht<Integer> k2 = new Koordinate2DGewicht<Integer>(1.1d,2.2d,9);
System.out.println(k2);
}
}

 

Achtung: Der formale Typparamter T der Klasses Koordinate2Gewicht wurde an dieser Stelle neu eingeführt. Er ist ein anderer als der formale Typparameter T der Oberklasse Koordinate!

Generische Unterklasse leitet aus nicht generischer Oberklasse ab

Eine generische Klasse auch eine nicht generische Klasse erweitern. Hier wird der Typ-Parmater neu in die Klassenhierarchie eingeführt. Die Klassendeklarationen genügen dann der folgenden Form:

public class Unterklasse<T> extends Oberklasse

Ein Beispiel hierfür ist eine nicht generische Oberklasse Koordinate2D aus der eine generische Unterklasse Koordinate2DGewichtGen<T> abgeleitet wird:

package s2.generics;
/**
*
* @author s@scalingbits.com
*/
public class Koordinate2D {
private Double x;
private Double y;

public Double getX() {return x;}
public void setX(Double x) {this.x = x;}
public Double getY() {return y;}
public void setY(Double y) { this.y = y;}

public Koordinate2D(Double xp, Double yp ) {
x = xp;
y = yp;
}

@Override
public String toString() {return "x: " + x + "; y: " + y;}

public static void main (String[] args) {
Koordinate2D k1 = new Koordinate2D(2.2d, 3.3d);
System.out.println(k1);
}
}

 

 

public class Koordinate2DGewichtGen<T> extends Koordinate2D {
private T gewicht;

 

public T getGewicht() {return gewicht;}
public void setGewicht(T g) {gewicht = g;}

public Koordinate2DGewichtGen (Double x, Double y, T g) {
super (x,y);
gewicht = g;
}

@Override
public String toString() {return super.toString()+", Gewicht: "+ gewicht;}

public static void main (String[] args) {
Koordinate2DGewichtGen<Double> k1 = new Koordinate2DGewichtGen<Double>(1.1d, 2.2d, 9.9d);
double dx = k1.getX();
System.out.println(k1);

Koordinate2DGewichtGen<Integer> k2 = new Koordinate2DGewichtGen<Integer>(1.1d,2.2d,9);
System.out.println(k2);
}
}

 

Nicht generische Unterklasse leitet aus generischer Oberklasse ab

Die letzte Variante besteht aus nicht generischen Klassen die aus einer generischen Oberklasse ableiten in dem sie einen aktuellen Typ-Parameter für die Unterklasse aus der Oberklasse wählen. Die Klassendeklarationen dieser Klassen haben die folgende Schreibweise:

public class Unterklasse extends Oberklasse<konkrete-Klasse>

Ein Beispiel hierfür sei die Klasse Koordinate3DDouble die nicht generisch ist und für die x und y Koordinate die Klasse Koordinate mit dem aktuellen Typparameter Double verwendet:

package s2.generics;
/**
*
* @author s@scalingbits.com
*/
public class Koordinate3DDouble extends Koordinate<Double> {
private Double z;

public Double getZ() {return z;}
public void setZ(Double z) {this.z = z;}

@Override
public String toString() {return super.toString()+", z: "+ z;}

public Koordinate3DDouble (Double x, Double y, Double z) {
super (x,y);
this.z = z;
}

public static void main (String[] args) {
Koordinate3DDouble k1 = new Koordinate3DDouble(1.1d, 2.2d, 3.3d);
double d1 = k1.getX(); //Generezität nicht mehr sichtbar
System.out.println(k1);
}
}

 

 

 

 

Anonymous (not verified)

Tue, 06/14/2016 - 12:08

Müssten die Syntax-Regeln nicht eigentlich Oberklasse heißen, wenn ein konkreter Typ festgelegt wird um die generische, bzw nicht generische Unterklasse abzuleiten?

Ich verstehe Ihre Frage nicht so richtig.
Würden Sie vielleicht einen Vorschlag posten?

Danke.