06.03 Wildcards und Bounded Type Parameters
Ein praktisches Beispiel
In diesem Beispiel werden noch mal folgende Themen besprochen:
- Nach oben beschränkte Wildcard Typen
- Unbeschränkte Wildcard Typen
- Bounded Type Parameters
- Kleine Wiederholung der Vererbung
Zur Veranschaulichung dieser Themen bauen wir uns einen kleinen Zoo mit Käfigen für unterschiedliche Tiere. Es wird insgesamt drei Tiere geben – Aras, Graupapageien und Löwen. Hierzu legen Sie sich zuerst einmal die Klasse Animal
an. Ein Animal
bekommt einen Namen und kann gefüttert werden.
package de.jbb.wildcards; public class Animal { private String name = null; protected Animal(String name) { this.name = name; } public void feed() {} public String getName() { return this.name; } }
Da es keine „allgemeinen Tiere“ gibt, ist es zwingend erforderlich, dass unsere Animal
Klasse noch mal genauer spezifiziert wird. Deshalb wird der Konstruktor als protected
modifiziert, damit keine Instanz der Klasse Animal
von außerhalb erstellt werden kann. Direkt von dieser Klasse erben die Löwen:
package de.jbb.wildcards; public class Lion extends Animal { public Lion(String name) { super(name); } }
Unsere Graupapageien und Aras erben nicht direkt von Animal
, da sie noch eine weitere Gemeinsamkeit haben. Beide Tiere sind Vögel und können zwitschern. Wir benötigen also eine Zwischenklasse Bird
.
package de.jbb.wildcards; public class Bird extends Animal { protected Bird(String name) { super(name); } public void chirp() {} }
Auch hier ist es nicht sinnvoll (ebenso wie bei der Klasse Animal
) direkt eine Instanz der Klasse Bird
von außerhalb zu erstellen, weshalb wir dies mit einem geschützten Konstruktor unterbinden. Unsere spezialisierten Vogel-Klassen unterscheiden sich nur geringfügig von der Löwen-Klasse:
package de.jbb.wildcards; public class GrayParrot extends Bird { public GrayParrot(String name) { super(name); } }
package de.jbb.wildcards; public class Macaw extends Bird { public Macaw(String name) { super(name); } }
Als nächsten Schritt erstellen wir unseren Käfig. Ein Käfig enthält beliebige Tiere gleicher Art (Bounded Type Parameters). Da es aber nicht sinnvoll ist, nur ein Tier pro Käfig zu halten, können sich mehrere Tiere in einem Käfig aufhalten. Aus Kapitel 06.02 Generics wissen Sie, dass Sie keine Arrays von generischen Typen erstellen können. Deshalb wird an dieser Stelle dem Kapitel 08. Collection Framework vorgegriffen.
Es gibt in Java so etwas wie dynamische Arrays. Dieser dynamischen Arrays nennen sich
ArrayList
und sind ebenfalls generisch. Mit der MethodeArrayList.add
können Objekte zu einerArrayList
hinzugefügt, mitArrayList.remove
entfernt, und mitArrayList.get
abgefragt werden. Der Speicher einerArrayList
ist dabei nicht wie bei einem Array statisch, sondern erweitert bzw. verringert sich dynamisch und kann mitArrayList.size
abgefragt werden. Mehr müssen Sie momentan nicht über dieArrayList
wissen.
Es muss möglich sein dem Käfig Tiere hinzuzufügen, Tiere wieder wegzunehmen, einzelne Tiere abzufragen, und festzustellen, wie viele Tiere sich momentan im Käfig befinden. Aus diesen Vorgaben resultiert folgender Code:
package de.jbb.wildcards; import java.util.ArrayList; public class Cage<Ani extends Animal> { private ArrayList<Ani> animals = null; public Cage() { this.animals = new ArrayList<Ani>(); } public void addAnimal(Ani animal) { this.animals.add(animal); } public void removeAnimal(Ani animal) { this.animals.remove(animal); } public Ani getAnimal(int pos) { return this.animals.get(pos); } public int getAnimalCount() { return this.animals.size(); } }
Als letzte Klasse benötigen wir eine Repräsentation des eigentlichen Zoos. Zu Gunsten der Einfachheit dieses Beispiels läuft alles in dieser Klasse in der Main-Methode sequentiell ab. Wir erstellen uns drei Käfige. Einen für Aras, einen für Graupapageien und einen für Löwen. Außerdem benötigen wir zwei Methoden. Eine akzeptiert Käfige mit beliebigen Tieren (hier kann der unbeschränkte Wildcard Typ verwendet werden, da die Klasse Cage
bereits durch Bounded Type Parameters auf Tiere beschränkt wurde) und füttert selbige, eine andere akzeptiert nur Käfige mit Vögeln (nach oben beschränkter Wildcard Typ) und lässt diese zwitschern.
package de.jbb.wildcards;
public class Zoo {
public static void main(String[] args) {
Cage
grayParrotCage.addAnimal(new GrayParrot(„Polly“));
grayParrotCage.addAnimal(new GrayParrot(„Oscar“));
Cage
macawCage.addAnimal(new Macaw(„Jacob“));
macawCage.addAnimal(new Macaw(„Vreni“));
macawCage.addAnimal(new Macaw(„Stefan“));
Cage
lionCage.addAnimal(new Lion(„Rocky“));
lionCage.addAnimal(new Lion(„Lorreta“));
letTheBirdsChirp(grayParrotCage);
letTheBirdsChirp(macawCage);
// letTheBirdsChirp(lionCage); Compiler-Error
feedTheAnimals(grayParrotCage);
feedTheAnimals(macawCage);
feedTheAnimals(lionCage);
}
public static void feedTheAnimals(Cage> cage) {
for (int i = 0; i < cage.getAnimalCount(); i++) { cage.getAnimal(i).feed(); } } public static void letTheBirdsChirp(Cage extends Bird> birdCage) {
for (int i = 0; i < birdCage.getAnimalCount(); i++) { birdCage.getAnimal(i).chirp(); } } }[/sourcecode]