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 Methode ArrayList.add können Objekte zu einer ArrayList hinzugefügt, mit ArrayList.remove entfernt, und mit ArrayList.get abgefragt werden. Der Speicher einer ArrayList ist dabei nicht wie bei einem Array statisch, sondern erweitert bzw. verringert sich dynamisch und kann mit ArrayList.size abgefragt werden. Mehr müssen Sie momentan nicht über die ArrayList 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 = new Cage();
grayParrotCage.addAnimal(new GrayParrot(„Polly“));
grayParrotCage.addAnimal(new GrayParrot(„Oscar“));

Cage macawCage = new Cage();
macawCage.addAnimal(new Macaw(„Jacob“));
macawCage.addAnimal(new Macaw(„Vreni“));
macawCage.addAnimal(new Macaw(„Stefan“));

Cage lionCage = new 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 birdCage) {

for (int i = 0; i < birdCage.getAnimalCount(); i++) { birdCage.getAnimal(i).chirp(); } } }[/sourcecode]

Previous Article
Next Article

Schreibe einen Kommentar

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.