Lernpfad:Objektorientierte Programmierung mit Java/Generische Typen: Unterschied zwischen den Versionen

Aus Informatik-Box
Zur Navigation springen Zur Suche springen
Keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
 
Zeile 9: Zeile 9:
Manchmal weiß man bei der Implementierung einer Klasse aber noch nicht, welchen Datentypen alle {{Pfad|Objektvariablen}} haben sollen, oder es ist wünschenswert, eine Klasse so zu implementieren, dass sie verschiedene Datentypen aufnehmen kann (''Datenstrukturen'' sind ein solches Beispiel).
Manchmal weiß man bei der Implementierung einer Klasse aber noch nicht, welchen Datentypen alle {{Pfad|Objektvariablen}} haben sollen, oder es ist wünschenswert, eine Klasse so zu implementieren, dass sie verschiedene Datentypen aufnehmen kann (''Datenstrukturen'' sind ein solches Beispiel).


Um dies zu erlauben gibt es in Java '''Generische Klassen''', die '''Generische Datentypen''' verwenden.  
Um dies zu erlauben, gibt es in Java '''Generische Klassen''', die '''Generische Datentypen''' verwenden.  


''Generische Typen'' werden erst konkret festgelegt, wenn eine {{Pfad|Objekte erstellen|neue Objektinstanz einer Klasse}} erstellt wird. Bei der Implementierung benutzt man noch einen Platzhalter.
''Generische Typen'' werden erst konkret festgelegt, wenn eine {{Pfad|Objekte erstellen|neue Objektinstanz einer Klasse}} erstellt wird. Bei der Implementierung benutzt man noch einen Platzhalter.
Zeile 30: Zeile 30:
</syntaxhighlight>
</syntaxhighlight>


Die Klasse <code>Kiste</code> oben ist eine ''generische Klasse'' mit dem ''generischen Typ'' <code>Inhaltstyp </code>. Er wird durch die Spitzen Klammern (<code><></code>) gekennzeichnet. Der ''generische Typ'' wird wie jeder andere Typ verwendet (zum Beispiel bei der Deklaration der Objektvariablen <code>inhalt</code> oder im entsprechenden Getter und Setter), ohne das es diesen Typ in Java gibt. Möchte man nun ein Objekt der Klasse <code>Kiste</code> erstellen, dann muss man den konkreten Typ des Inhalts mit angeben:
Die Klasse <code>Kiste</code> oben ist eine ''generische Klasse'' mit dem ''generischen Typ'' <code>Inhaltstyp </code>. Er wird durch die spitzen Klammern (<code><></code>) gekennzeichnet. Der ''generische Typ'' wird wie jeder andere Typ verwendet (zum Beispiel bei der Deklaration der Objektvariablen <code>inhalt</code> oder im entsprechenden ''Getter'' und ''Setter''), ohne das es diesen Typ in Java gibt. Möchte man nun ein Objekt der Klasse <code>Kiste</code> erstellen, dann muss man den konkreten Typ des Inhalts mit angeben:
<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
Kiste<String> eineKisteVollText = new Kiste<String>("Hallo, Welt!");
Kiste<String> eineKisteVollText = new Kiste<String>("Hallo, Welt!");
Zeile 82: Zeile 82:


== Darstellung im Klassendiagramm ==
== Darstellung im Klassendiagramm ==
Im [[Implementierungsklassendiagramm]] wird eine ''generische Klasse'' wie andere Klassen dargestellt. Der generische Typparameter wird wie im Quelltext ergänzt und in den Methoden- und Variablen-Signaturen wie gewohnt verwendet.
Im [[Implementierungsklassendiagramm]] wird eine ''generische Klasse'' wie andere Klassen dargestellt. Der generische Typ-Parameter wird wie im Quelltext ergänzt und in den Methoden- und Variablen-Signaturen wie gewohnt verwendet.
[[Datei:Generics_Kiste_1.png|center]]
[[Datei:Generics_Kiste_1.png|center]]


Wird eine generische Klasse von anderen Klassen referenziert, um Daten zu speichern, dann wird der konkrete Inhaltstyp als zusätzliche Notiz an die generische Klasse geschrieben. in der Regel werden dann nicht nochmal alle Objektmethoden der generischen Klasse aufgelistet. Dies ist vor allem für die Modellierung mit [[Datenstrukturen]] relevant.
Wird eine generische Klasse von anderen Klassen referenziert, um Daten zu speichern, dann wird der konkrete Inhaltstyp als zusätzliche Notiz an die generische Klasse geschrieben. In der Regel werden dann nicht erneut alle Objektmethoden der generischen Klasse aufgelistet. Dies ist insbesondere für die Modellierung mit [[Datenstrukturen]] relevant.
[[Datei:Generics_Kiste_2.png|center]]
[[Datei:Generics_Kiste_2.png|center]]


Zeile 94: Zeile 94:
# Implementiere eine Klasse <code>Zoo</code>, die einen Käfig für ''Bienen'' und einen für ''Frösche'' als Objektvariablen enthält. [[Datei:Generics_Zoo_1.png|center]]
# Implementiere eine Klasse <code>Zoo</code>, die einen Käfig für ''Bienen'' und einen für ''Frösche'' als Objektvariablen enthält. [[Datei:Generics_Zoo_1.png|center]]
# Erweitere das Programm nach eigenem Ermessen um folgende Aspekte:
# Erweitere das Programm nach eigenem Ermessen um folgende Aspekte:
#* Ein Käfig kann mehrere Tiere derselben Art aufnehmen. Implementieren sie dies in der Klasse <code>Käfig</code> mit einem ''generischen Array''.
#* Ein Käfig kann mehrere Tiere derselben Art aufnehmen. Implementiere dies in der Klasse <code>Käfig</code> mit einem ''generischen Array''.
#* Ein Zoo kann mehrere Käfige mit derselben Tierart ausstellen. Implementieren sie dies in der Klasse <code>Zoo</code> mit einem Arrays von Käfigen.
#* Ein Zoo kann mehrere Käfige mit derselben Tierart ausstellen. Implementiere dies in der Klasse <code>Zoo</code> mit einem Array von Käfigen.
#* Der Zoo stellt Käfige ähnlicher Tiere (Amphibien, Reptilien, Vögel, Fische, ...) zusammen in Häusern aus (Reptilienhaus, ...). Erstellen sie entsprechende Oberklassen für Tiere und eine generische Klasse ''Tierhaus<Tierklasse>'', die mehrere Käfige von Tieren dieser Oberklasse enthalten.
#* Der Zoo stellt Käfige ähnlicher Tiere (Amphibien, Reptilien, Vögel, Fische, ...) zusammen in Häusern aus (Reptilienhaus, ...). Erstelle entsprechende Oberklassen für Tiere und eine generische Klasse ''Tierhaus<Tierklasse>'', die mehrere Käfige von Tieren dieser Oberklasse enthalten.
{{Aufgabe:End}}
{{Aufgabe:End}}
{{Lösung:Start}}
{{Lösung:Start}}

Aktuelle Version vom 7. Februar 2022, 23:42 Uhr

Generische Typen und Klassen

Ein Datentyp bestimmt die Art der Informationen, die in einer Variablen gespeichert werden können. Dieser Typ muss bei der Deklaration der Variablen strikt festgelegt werden.

int zahl = 0;
String text = "Hallo, Welt!"

Manchmal weiß man bei der Implementierung einer Klasse aber noch nicht, welchen Datentypen alle Objektvariablen haben sollen, oder es ist wünschenswert, eine Klasse so zu implementieren, dass sie verschiedene Datentypen aufnehmen kann (Datenstrukturen sind ein solches Beispiel).

Um dies zu erlauben, gibt es in Java Generische Klassen, die Generische Datentypen verwenden.

Generische Typen werden erst konkret festgelegt, wenn eine neue Objektinstanz einer Klasse erstellt wird. Bei der Implementierung benutzt man noch einen Platzhalter.

public class Kiste<Inhaltstyp> {
  private Inhaltstyp inhalt;

  public Kiste( Inhaltstyp pInhalt ) {
    inhalt = pInhalt;
  }

  public Inhaltstyp getInhalt() {
    return inhalt;
  }

  public void setInhalt( Inhaltstyp pInhaltNeu ) {
    inhalt = pInhaltNeu;
  }
}

Die Klasse Kiste oben ist eine generische Klasse mit dem generischen Typ Inhaltstyp . Er wird durch die spitzen Klammern (<>) gekennzeichnet. Der generische Typ wird wie jeder andere Typ verwendet (zum Beispiel bei der Deklaration der Objektvariablen inhalt oder im entsprechenden Getter und Setter), ohne das es diesen Typ in Java gibt. Möchte man nun ein Objekt der Klasse Kiste erstellen, dann muss man den konkreten Typ des Inhalts mit angeben:

Kiste<String> eineKisteVollText = new Kiste<String>("Hallo, Welt!");
System.out.println(eineKisteVollText.getInhalt()); // Gibt aus: Hallo, Welt!

Wrapper-Klassen

Eine Einschränkung generischer Typen ist, dass sie konkret nicht mit einem der primitiven Datentypen (int, boolean, ...) belegt werden können. Folgendes geht also nicht:

Kiste<int> zahlA = new Kiste<int>(4); // Fehler !!!
System.out.println(zahlA.getInhalt() + 6);

Die konkreten Typen müssen immer komplexe Datentypen (also Klassen) sein. Um dennoch Zahlen oder Wahrheitswerte benutzen zu können, gibt es in Java Wrapper-Klassen (dt. Hülle) für jeden primitiven Typ. Für den primitiven Typ int ist dies zum Beispiel Integer. Damit kann das Programm oben so umgesetzt werden:

Kiste<Integer> zahlA = new Kiste<Integer>(4);
System.out.println(zahlA.getInhalt() + 6); // Gibt aus: 10
Icon Info.png

Man würde erwarten, dass der Kiste als Inhalt auch eine Objektinstanz der Klasse Integer übergeben werden müsste. Dies ist auch der Fall, allerdings hilft Java hier aus, indem der Compiler die 4 implizit in ein new Integer(4) umwandelt.

Die Liste der Wrapper-Klassen kann der Tabelle entnommen werden:

Typname Wrapper-Klasse Verwendungsbeispiel
boolean Boolean Boolean b = new Boolean(true);
char Character Character c = new Character('a');
byte Byte Byte b = new Byte(4);
short Short Short s = new Short(8);
int Integer Integer i = new Integer(98271);
long Long Long l = new Long(98271L);
float Float Float f = new Float(0.1f);
double Double Double d = new Double(0.1);

Darstellung im Klassendiagramm

Im Implementierungsklassendiagramm wird eine generische Klasse wie andere Klassen dargestellt. Der generische Typ-Parameter wird wie im Quelltext ergänzt und in den Methoden- und Variablen-Signaturen wie gewohnt verwendet.

Generics Kiste 1.png

Wird eine generische Klasse von anderen Klassen referenziert, um Daten zu speichern, dann wird der konkrete Inhaltstyp als zusätzliche Notiz an die generische Klasse geschrieben. In der Regel werden dann nicht erneut alle Objektmethoden der generischen Klasse aufgelistet. Dies ist insbesondere für die Modellierung mit Datenstrukturen relevant.

Generics Kiste 2.png

Aufgabe

Icon Heft.png
Arbeitsauftrag

Wir implementieren einen Zoo für die Tiere aus dem Schritt Vererbung:

  1. Implementiere eine Klasse Käfig<Tierart>, die analog zur Kiste oben eine Tierart aufnehmen kann.
    Generics Käfig.png
  2. Implementiere eine Klasse Zoo, die einen Käfig für Bienen und einen für Frösche als Objektvariablen enthält.
    Generics Zoo 1.png
  3. Erweitere das Programm nach eigenem Ermessen um folgende Aspekte:
    • Ein Käfig kann mehrere Tiere derselben Art aufnehmen. Implementiere dies in der Klasse Käfig mit einem generischen Array.
    • Ein Zoo kann mehrere Käfige mit derselben Tierart ausstellen. Implementiere dies in der Klasse Zoo mit einem Array von Käfigen.
    • Der Zoo stellt Käfige ähnlicher Tiere (Amphibien, Reptilien, Vögel, Fische, ...) zusammen in Häusern aus (Reptilienhaus, ...). Erstelle entsprechende Oberklassen für Tiere und eine generische Klasse Tierhaus<Tierklasse>, die mehrere Käfige von Tieren dieser Oberklasse enthalten.