@@ -4,18 +4,19 @@ title: "Generics2: Bounds & Wildcards"
44---
55
66::: tldr
7- Typ-Variablen können weiter eingeschränkt werden, in dem man einen verpflichtenden
8- Ober- oder Untertyp angibt mit ` extends ` bzw. ` super ` . Damit muss der später bei der
9- Instantiierung verwendete Typ-Parameter entweder die Oberklasse selbst sein oder
10- davon ableiten (bei ` extends ` ) bzw. der Typ-Parameter muss eine Oberklasse der
11- angegebenen Schranke sein (` super ` ).
12-
13- Durch die Einschränkung mit ` extends ` können in der Klasse/Methode auf der
14- Typ-Variablen alle Methoden des angegebenen Obertyps verwendet werden.
15-
16- Ein Wildcard (` ? ` ) als Typ-Parameter steht für einen beliebigen Typ, wobei die
17- Typ-Variable keinen Namen bekommt und damit innerhalb der Klasse/Methode nicht
18- zugreifbar ist.
7+ Typ-Parameter können durch ** Bounds** eingeschränkt werden: ` <T extends ...> `
8+ bedeutet, dass der Typ-Parameter ` T ` nach oben eingeschränkt wird ("upper bound").
9+ Durch ` extends ` -Bounds kann in einer Klasse bzw. Methode der Typ-Parameter so
10+ eingeschränkt werden, dass alle Methoden des Obertyps verwendet werden können.
11+
12+ Ein ** Wildcard** (` ? ` ) steht für einen unbestimmten Typ. Ein Wildcard-Typ hat keinen
13+ Namen / ist nicht benennbar und ist innerhalb der Klasse/Methode nicht direkt
14+ zugreifbar. Wildcards können mit ` ? extends ... ` nach oben ("upper bound") oder
15+ ` ? super ... ` nach unten ("lower bound") eingeschränkt werden.
16+
17+ Bei ` ? extends Bound ` muss der konkrete Typ die Schranke selbst oder ein Subtyp
18+ davon sein. Bei ` ? super Bound ` muss der konkrete Typ ein Supertyp (Obertyp) der
19+ angegebenen Schranke sein.
1920:::
2021
2122::: youtube
@@ -40,20 +41,29 @@ Cps<String> c; // Fehler!!!
4041
4142- Schlüsselwort ` extends ` gilt hier auch für Interfaces
4243
43- - Mehrere Interfaces: nach ` extends ` Klasse oder Interface, danach mit " ` & ` "
44- getrennt die restlichen Interfaces:
44+ - Mehrere Interfaces: nach ` extends ` ** eine ** Klasse oder ** ein ** Interface,
45+ danach mit " ` & ` " getrennt die restlichen Interfaces:
4546
4647 ``` java
4748 class Cps <E extends KlasseOderInterface & I1 & I2 & I3 > {}
4849 ```
4950
50- ::: notes
51+ :::: notes
52+ Falls eine Klasse einem gemeinsamen Obertyp folgen soll, können mehrere Bound - Typen
53+ durch `& ` verbunden werden. Der erste Bound kann eine Klasse (z. B . `Number `) sein;
54+ alle weiteren Bound - Typen müssen Interfaces sein. Wenn kein Klassen - Bound existiert,
55+ können alle Bound - Typen Interfaces sein.
56+
57+ ::: tip
5158* Anmerkung * : Der Typ - Parameter ist analog auch mit `super ` (nach unten)
52- einschränkbar
59+ einschränkbar. Das schauen wir uns im Zusammenhang mit Vererbungsbeziehungen und
60+ Polymorphie im dritten Teil [" Generics3: Generics und
61+ Polymorphie" ](generics3- polymorphism. md) noch genauer an.
62+ :::
5363
5464[Beispiel bounds. Cps ]{. ex
5565href= " https://github.com/Programmiermethoden-CampusMinden/Prog2-Lecture/blob/master/lecture/java-classic/src/bounds/Cps.java" }
56- :::
66+ ::::
5767
5868# Wildcards : Dieser Typ ist mir nicht so wichtig
5969
@@ -80,17 +90,58 @@ public class Wuppie {
8090 nutzbar ...
8191
8292::: notes
93+ Die Wildcard ` ? ` steht für einen unbekannten Typ. ` List<?> ` erlaubt ` List ` -Objekte
94+ jedes Typs, aber innerhalb der Methode kann man nicht sicher auf spezifische
95+ Eigenschaften des konkreten Typs zugreifen. ` List<?> ` ist also ** nicht** eine "Liste
96+ von ` Object ` ", sondern "Liste von unbekanntem Typ".
97+
98+ - Typvariable: "ich benenne den Typ und kann ihn mehrfach verwenden"
99+ - Wildcard: "ich akzeptiere etwas Unbekanntes, kann es aber nicht benennen"
100+
101+ Mit ` List<? extends A> ` erlaubt man Listen von Elementen, die ` A ` oder eine
102+ Unterklasse von ` A ` sind (* kovariant* , siehe auch Diskussion in [ "Generics3:
103+ Generics und Polymorphie"] ( generics3-polymorphism.md ) ); man kann Elemente als ` A `
104+ lesen/nutzen, aber nicht sicher als ` A ` hinzufügen (weil der echte Typ wg. des
105+ Wildcards unbekannt ist - es könnte ein beliebiger Untertyp von ` A ` sein).
106+
83107Weitere Eigenschaften:
84108
85109- Durch Wildcard kein Zugriff auf den Typ
86110- Wildcard kann durch upper bound eingeschränkt werden
87- - Geht nicht bei Klassen-/Interface-Definitionen
111+ - Geht nicht bei Klassen-/Interface-Definitionen, hier wird eine Typ-Variable
112+ benötigt
113+
114+ Weitere Beispiele:
115+
116+ - ` List<?> ` - Typ der Listenelemente unbekannt, nur Methoden von ` Object ` nutzbar
117+ - ` List<? extends T> ` - Typ der Listenelemente ist ` T ` oder eine Unterklasse von
118+ ` T ` ; Zugriff lesend mit den Methoden von ` T ` (außer ` null ` ), Schreiben nur
119+ eingeschränkt möglich (konkreter Typ unklar wg. ` ? ` - es könnte eine Unterklasse
120+ von ` T ` sein, und Schreiben von Elementen vom Typ ` T ` würde (wenn es erlaubt
121+ wäre) dann zur Laufzeit schief gehen - Java fängt das aber zur Compilezeit ab)
122+ - ` List<? super T> ` - Typ der Listenelemente ist ` T ` oder eine Oberklasse von ` T ` ;
123+ Zugriff schreibend möglich mit Werten vom Typ ` T ` und Untertypen, Lesen nur mit
124+ ` Object ` (der konkrete Typ samt Schnittstelle ist unklar: es könnte eine
125+ beliebige Oberklasse von ` T ` sein, die eine völlig unterschiedliche
126+ Schnittstelle als ` T ` hat)
127+
128+ =\> Das soll uns als erste Einführung von Bounds und Wildcards reichen. Wir werden
129+ überwiegend die ` extends ` -Bounds verwenden. Für eine genauere Diskussion von "Type
130+ Erasure" (TE) und "Producer extends, Consumer super" (PECS-Regel) sowie die
131+ Varianz-Diskussion siehe Lektion [ "Generics3: Generics und
132+ Polymorphie"] ( generics3-polymorphism.md ) .
88133:::
89134
90135\bigskip
91136\bigskip
92137
93- @Bloch2018 : Nur für Parameter und nicht für Rückgabewerte nutzen!
138+ @Bloch2018 : Wildcards ** meist** für Parameter; Rückgabewerte ** möglichst** konkret
139+ typisieren.
140+
141+ ::: notes
142+ Generische Typen in Rückgabewerten sollten möglichst konkrete Typen oder Bounds
143+ verwenden, um Typ-Sicherheit zu wahren.
144+ :::
94145
95146# Hands-On: Ausgabe für generische Listen
96147
@@ -115,9 +166,11 @@ public class X {
115166}
116167```
117168
118- [ ** Hinweis** : Dieses Beispiel beinhaltet auch Polymorphie bei/mit generischen
119- Datentypen, bitte vorher auch das Video zum vierten Teil "Generics und Polymorphie"
120- anschauen] {.notes}
169+ ::: notes
170+ ** Hinweis** : Dieses Beispiel berührt auch Polymorphie bei/mit generischen
171+ Datentypen, vgl. dritter Teil [ "Generics und
172+ Polymorphie"] ( generics3-polymorphism.md ) anschauen.
173+ :::
121174
122175::: notes
123176## Erster Versuch (* A* und * B* und * main()* wie oben)
@@ -130,7 +183,7 @@ public class X {
130183}
131184```
132185
133- =\> ** So gehts nicht!** Eine ` List<B> ` ist ** keine** ` List<A> ` (auch wenn ein ` B `
186+ =\> ** So geht's nicht!** Eine ` List<B> ` ist ** keine** ` List<A> ` (auch wenn ein ` B `
134187ein ` A ` ist, vgl. spätere Sitzung zu Generics und Vererbung ...)!
135188
136189[ Beispiel wildcards.v1.X] {.ex
@@ -168,7 +221,7 @@ public class X {
168221Das ist die Lösung. Man erlaubt als Argument nur ` List ` -Objekte und fordert, dass
169222sie mit ` A ` oder einer Unterklasse von ` A ` parametrisiert sind. D.h. in der Schleife
170223kann man sich auf den gemeinsamen Obertyp ` A ` abstützen und hat dann auch wieder die
171- ` printInfo ` -Methode zur Verfügung ...
224+ ` printInfo ` -Methode (von ` A ` ) zur Verfügung ...
172225:::
173226
174227[ Konsole wildcards.v3.X] {.ex
0 commit comments