"Grundkurs Programmieren in Java - (8. Auflage, 2018)"
2001-2018, Carl Hanser Verlag
Lösungsvorschlag zu Aufgabe 10.7 (Version 3.0)
(c) 2001-2018 D. Ratz, D. Schulmeister-Zimolong, D. Seese, J. Wiesenberger
Zeile 40:
Konzert konzert2 = new Konzert(roadie2,roadie2,roadie3);
Diese Zeile ist falsch, da
roadie2 = new Roadie<Performer>()
sich nicht in
Roadie<? extends Zuschauer>
umwandeln lässt. Die Klasse
Performer
ist keine Subklasse der Klasse
Zuschauer
(und eben dies wird fuer das erste Konstruktor-Element verlangt).
Zeile 44:
Konzert konzert6 = new Konzert(roadie6,roadie2,roadie3);
Diese Zeile entspricht einem Konstruktor-Aufruf mit den Typen
Konzert(
Roadie<Person>,
Roadie<Performer>,
Roadie<HuebschesGroupie>).
Die genaue geforderte Signatur des Konstruktors ist
Konzert(
Roadie<? extends Zuschauer> vorderEingang,
Roadie<? super Star> hinterEingang,
Roadie<? extends Groupie> backstage
Es gilt:
Performer
ist eine Superklasse von
Star
und
HuebschesGroupie
ist eine Unterklasse von
Groupie
- somit sind hier die Anforderungen erfüllt. Die
Klasse
Person
ist aber keine Unterklasse von
Zuschauer
- somit ist das erste Argument des Konstruktors nicht gültig.
Zeile 46:
Konzert besondersLax = new Konzert(roadie7,roadie7,roadie7);
Wer in dieser Zeile einen Fehler gefunden hat, dem sei versichert, dass dem
nicht so ist (zumindest nicht zur Compilierzeit). Die Instanz
roadie7
wurde als "roher" Typ
new Roadie()
erzeugt; der Übersetzer hat somit keine Informationen
bezüglich seiner Spezialisierung. Der Compiler lässt den Programmierer hier
gewähren und wird lediglich eine Warnung anzeigen.
In der Aufgabe wurde spezifiziert, dass "durch den Hintereingang
nur Bühnenpersonal (Performer) und der Star des Abends gelassen werden" soll.
Unsere Klasse
Konzert
definiert für den Hintereingang jedoch einen Roadie wie folgt:
private Roadie<? super Star> hinterEingang;
Gemäß unserer aktuellen Klassenhierarchie könnten wir hierfür die folgenden Roadies
definieren:
Roadie<Star>
Roadie<Performer>
Roadie<Person>
Aber:
Roadie<Object>
ist nicht möglich, da die Klasse als
Roadie<T extends Person>
definiert ist.
Im Falle der Klasse
Roadie<Performer>
hätten wir unser Ziel erreicht: nur Performers und der Star des Abends werden eingelassen. Die Ausprägung
Roadie<Star>
wäre zu exklusiv: Performer hätten keinerlei Zutritt, da sie sich nicht von Star
ableiten.
Roadie<Person>
wiederum wäre zu lax: in diesem Fall hätte
jede Person (also auch normale Zuschauer oder Groupies) Einlass.
Die Lösung des Problems ist, in diesem Fall auf Wildcards zu verzichten. Der Konstruktor sollte in
Konzert(
Roadie<? extends Zuschauer> vorderEingang,
Roadie<Performer> hinterEingang,
Roadie<? extends Groupie> backstage)
geändert werden.
PS: Von diesem konzeptionellen Fehler abgesehen ist es üblicherweise kein gutes Design, "Zugangsrechte"
über eine Klassenhierarchie abzubilden. Derartige Rechte sind naturgemäß dynamisch und ändern sich
oftmals über die Zeit. Beispiel: der Star des Abends hat eines seiner Groupies geheiratet. Wenn der Star
das Konzerthaus durch den Hintereingang betreten will und der Roadie diesem speziellen Groupie den
Eintritt verweigert, kann dies schwerwiegende Folgen für den Konzertveranstalter haben.