Generische Datentypen Zur Erinnerung: Mit Generischen

Werbung
Generische Datentypen
•
•
•
•
•
Programmierung (fortgeschrittene Konzepte)
Generische Programmierung in Java
Wolf-Ulrich Raffel
([email protected])
19.10.2005
Generische Programmierung in Java
1
Zur Erinnerung:
Generische Programmierung in Java
19.10.2005
3
19.10.2005
Generische Programmierung in Java
4
Die Schnittstelle Iterator
• Alte Version (vereinfacht):
• Alte Version:
public class Vector implements Collection{
public void add (Object o) {...}
public Iterator iterator() {...}
}
public interface Iterator{
boolean hasNext ();
Object next();
}
• Neue Version (vereinfacht):
• Neue Version:
public class Vector<T> implements Collection<T>{
public void add (T o) {...}
public Iterator<T> iterator() {...}
Generische Programmierung in Java
2
Vector meineGeomObjekte = new Vector<GeomObjekt>();
meinGeomObjekte.add(new Quadrat(3.0));
meinGeomObjekte.add(new Fahrrad()); //falsch!
...
Iterator<GeomObjekt> iter = meineGeomObjekte.iterator();
while (iter.hasNext()) {
GeomObjekt o = iter.next();
println(o.flaecheninhalt());
}
Die Klasse Vector
19.10.2005
Generische Programmierung in Java
Mit Generischen Datentypen:
Vector meineGeomObjekte = new Vector();
meinGeomObjekte.add(new Quadrat(3.0));
meinGeomObjekte.add(new Fahrrad()); //sinnlos, aber
erlaubt
...
Iterator iter = meineGeomObjekte.iterator();
while (iter.hasNext()) {
Object o = iter.next();
if (o instanceof GeomObjekt) { //zur Sicherheit
println(((GeomObjekt)o).flaecheninhalt());
}
}
19.10.2005
„Generics“
Verfügbar ab Java (1.)5.0.
Vorher separate Sprache: „Generic Java“
Vermeidet unnötige Typecasts
Ermöglicht Collections mit anderen Typen
als Objects
5
public interface Iterator<T>{
boolean hasNext ();
T next();
}
19.10.2005
Generische Programmierung in Java
6
1
Eigene Generics definieren
Unterklassen bei Generics
• Ein Quadrat ist ein Rechteck, aber:
• Java API enthält viele generische Klassen
(Vector, Iterator,...)
• Man kann selbst Generics definieren
• Generischer Code wird nicht für jede
Instanz kopiert (anders als in C++)
• Namenskonvention für Typparameter:
einzelne Grossbuchstaben
19.10.2005
Generische Programmierung in Java
Vector<Quadrat> quadrate = new Vector<Quadrat>();
Vector<Rechteck> rechtecke = quadrate; //falsch
• Sieht erlaubt aus, scheitert aber deswegen:
rechtecke.add(new Rechteck(2.5,1.5));
Quadrat q = quadrate.get(0);
• Problem ist bereits von Feldern bekannt:
Quadrat[] quadrate = new Quadrat[10];
Rechteck[] rechtecke = quadrate;
rechtecke[0] = new Rechteck(2.5,1.5); //erzeugt
ArrayStoreException
7
19.10.2005
Wildcards
• Statt Object kann man ein Wildcard verwenden
static void printAll (Vector<?> v) {
Iterator<?> iter = v.iterator();
while (iter.hasNext()) {
Object o = (iter.next()); //geht!
System.out.println(o);
}
}
static void printAll (Vector<Object> v) {
Iterator<Object> iter = v.iterator();
while (iter.hasNext()) {
Object o = (iter.next());
System.out.println(o);
}
}
• Wildcard matcht alle Klassen
• Vector<?> ist Oberklasse aller Vector-Klassen
• Zuweisung an Object möglich, da Object Mutterklasse
• Funktioniert leider nur für Vector<Object>, aber
z.B. nicht für Vector<String>
Generische Programmierung in Java
9
Beschränkte Wildcards
Generische Programmierung in Java
10
• 2.Versuch: Mit Wildcards
static double flaechensumme (Vector<?> v) {
Iterator<?> iter = v.iterator();
double summe = 0.0;
while (iter.hasNext()) {
GeomObjekt o = (iter.next()); //falsch!
summe+=o.flaecheninhalt();
}
return summe;
}
static double flaechensumme (Vector<GeomObjekt> v) {
Iterator<GeomObjekt> iter = v.iterator();
double summe = 0.0;
while (iter.hasNext()) {
GeomObjekt o = (iter.next());
summe+=o.flaecheninhalt();
}
return summe;
}
• Geht nicht, Zuweisung nur an Object möglich
• Geht leider nur z.B. nicht für Vector<Quadrat>
Generische Programmierung in Java
19.10.2005
Beschränkte Wildcards (2)
• Angenommen, wir wollen die Flächeninhalte
Geometrischer Objekte aufsummieren
19.10.2005
8
Wildcards (2)
• Angenommen, wir wollen alle Elemente eines
Vectors ausgeben
19.10.2005
Generische Programmierung in Java
11
19.10.2005
Generische Programmierung in Java
12
2
Beschränkte Wildcards (3)
Schreiben bei Wildcards
• Lösung: Beschränkte Wildcards
• Schreiben in Vector mit durch „extends“ beschränktem
Wildcard nicht möglich!
static double flaechensumme
(Vector<? extends GeomObjekt> v) {
Iterator<? extends GeomObjekt> iter = v.iterator();
double summe = 0.0;
while (iter.hasNext()) {
GeomObjekt o = (iter.next());
summe+=o.flaecheninhalt();
}
return summe;
}
static void fuegeEinheitsQuadratHinzu
(Vector<? extends GeomObjekt> v) {
v.add(new Quadrat(1.0)); //geht nicht!
}
• Aber es geht das folgende
static void fuegeEinheitsQuadratHinzu
(Vector<Quadrat> v) {
v.add(new Quadrat(1.0));
}
• Geht für jeden Subtyp vom GeomObjekt
19.10.2005
Generische Programmierung in Java
13
Schreiben bei Wildcards (2)
19.10.2005
Generische Programmierung in Java
14
Zusammenfassung Wildcards
• Es geht auch jeder Supertyp von Quadrat:
• Nur Objekte lesen => einfache Wildcards
static void fuegeEinheitsQuadratHinzu
(Vector<GeomObjekt> v) {
v.add(new Quadrat(1.0));
}
void printAll (Vector<?> v)
• Nur geom.Objekte lesen => beschränkte
Wildcards mit extends
void read(Vector<? extends GeomObjekt> v)
• Allgemein lässt sich formulieren
• Nur geom.Objekte schreiben => beschränkte
Wildcards mit super
static void fuegeEinheitsQuadratHinzu
(Vector<? super Quadrat> v) {
v.add(new Quadrat(1.0));
}
void write(Vector<? super GeomObjekt> v)
• geom.Objekte lesen und schreiben => exakten Typ
verwenden
void readAndWrite(Vector<GeomObjekt> v)
19.10.2005
Generische Programmierung in Java
15
19.10.2005
Generische Methoden
Generische Programmierung in Java
16
Generische Methoden (2)
• Bisher nur generische Klassen und Schnittstellen
• Auch Methoden können generisch sein
• Bei Methodenaufruf braucht man Typparameter
nicht angeben
• Spezifischster Typ für Methode wird ausgewählt
19.10.2005
Generische Programmierung in Java
17
• Angenommen, wir wollen alle Elemente eines Feldes in
einem Vector speichern
static void arr2vec(Object[]a,Vector<?> v){
for (int i=0; i<a.length; i++) {
v.add(a[i]); //geht nicht!
}
}
• Mit generischen Methoden geht es:
static <T> void arr2vec(T[]a,Vector<? super T> v){
for (int i=0; i<a.length; i++) {
v.add(a[i]);
}
}
19.10.2005
Generische Programmierung in Java
18
3
Generische Methoden vs.
Wildcards
Generische Methoden vs.
Wildcards (2)
• Man kann formulieren:
• Generische Methoden nur verwenden, wenn
Typparameter mehrmals genutzt wird
interface Collection<E> {
<T> boolean containsAll(Collection<T> c);
<T extends E> void addAll(Collection<T> c);
}
static <T> void tausch0(Vector<T> v1, Vector<T> v2){
v1.add(v2.get(0));
v2.add(v1.get(0));
}
• Oder äquivalent (und eleganter) mit Wildcards:
• Verwendung von Wildcards geht nicht
interface Collection<E> {
boolean containsAll(Collection<?> c);
void addAll(Collection<? extends E> c);
}
19.10.2005
Generische Programmierung in Java
void tausch0(Vector<?> v1, Vector<?> v2){
v1.add(v2.get(0));//geht nicht
v2.add(v1.get(0));//geht nicht
}
19
Methodenauswahl
Vector<Quadrat> quadratV = new Vector<Quadrat>();
Vector<Rechteck> rechteckV = new Vector<Rechteck>();
Quadrat[] quadratA = new Quadrat[10];
...
20
• Ähnliches Problem beim Überladen von Methoden
bekannt:
void tueEtwas (GeomObjekt g1, GeomObjekt g2){...} //1
void tueEtwas (GeomObjekt g, Quadrat q){...}
//2
void tueEtwas (Quadrat q, Rechteck r){...}
//3
• Folgende Aufrufe werden durchgeführt:
• und führen folgende Aufrufe durch
tueEtwas
tueEtwas
tueEtwas
tueEtwas
arr2vec(quadratA,rechteckV);//T=Rechteck
arr2vec(rechteckA,quadratV);//geht nicht
arr2vec(quadratA,objectV);//T=Object
arr2vec(quadratA,kreisV);//geht nicht
Generische Programmierung in Java
Generische Programmierung in Java
Methodenauswahl bei Überladen
• Angenommen wir haben folgendes
19.10.2005
19.10.2005
(rechteck1, quadrat1);
(quadrat1, kreis1);
(quadrat1, object1);
(quadrat1, quadrat2);
//2 spez. als 1)
//nur 1 passt
//nichts passt
// 2 oder 3 ?
• Compilezeitfehler, wenn keine Methode passt oder
Auswahl mehrdeutig
21
19.10.2005
Generische Programmierung in Java
22
Abschlussbemerkungen
• Mehrere Typparameter möglich
public class MyClass <S,T> {...}
• Konstruktordeklaration ohne Typparameter
public class MyClass <S,T> {
public MyClass() {...} //richtig
public MyClass<S,T>() {...} //falsch
}
19.10.2005
Generische Programmierung in Java
23
4
Herunterladen