Programmieren_2/generics2.md

131 lines
3.1 KiB
Markdown

<!--
title: Generizität
description: Folien für Generizität in Programmieren 2
url: https://git.henriburau.de/tutorien/programmieren-2
header: Programmieren 2 **Tutorium**
footer: Henri Burau
-->
# Generizität
---
# Grundlagen
Durch Generizität können wir Typen, Klasse und Methoden parametrisieren. Der
genutzte Typ wird dann zur Laufzeit übergeben.
Genutzt wird dieses Sprachkonzept z.B. im Collection Framework.
```java
// Deklaration
class Test<T> {
public T gibHer(T type) { return type; }
}
```
```java
// Benutzung
Test<String> test;
String result = test.gibHer(test);
```
---
# Raw Types
Der Java-Compiler entfernt alle generischen Parameter und arbeitet dann auf den
**Raw Types**. Dieser Vorgang wird **Type Erasure** genannt. Das führt zu
Einschränkungen zur Laufzeit:
* Generische Klassen können keine statischen Felder haben
* Es können keine Instanzen aus generischen Typen erzeugt werden
* Es kann kein ``instanceof`` für generische Typen genutzt werden
* ... (vollständige Liste auf der [Java-Website](https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html))
---
# Subtyping und Vererbung
Stehen zwei Typen in einer Subtyp-Beziehung (``class Dreieck extends Form``) bedeutet das **nicht**, dass auch die parametrisierten Typen in einer Verbindung stehen.
```java
// Deklaration
class FlaechenVerarbeiter {
public void verarbeiteFlaechen(List<Form> liste) {
}
```
```java
// Benutzung
Dreieck dreieck = new Dreieck();
Verarbeiter verarbeiter = new Verarbeiter();
verarbeiter.verarbeiteFlaechen(dreieck); // Geht das?
```
---
# Wildcards
Werden genutzt um beliebige generische Type als Parameter, Feld, lokale Variable oder Rückgabetypen zu deklarieren.
Benutzt wird dieses Sprachkonzept wenn man z.B. auf Collections arbeiten will:
```java
class ListenSchreiber {
public void schreib(List<?> liste) {
for (Object elem: list) {
System.out.println(elem);
}
}
}
```
Warum wird hier nicht der Parameter-Typ ``List<Object>`` genutzt?
---
## Lower Bounds
Beschränkt den Wildcard Typen nach unten. Dafür wird das Schlüsselwort ``super`` verwendet.
```java
// Hierarchie Object -> Number -> Integer
class IntegerSammler {
public void schreib(List<? super Integer> liste) {
for (int i = 0; i <= 10; i++) {
liste.add(i);
}
}
}
```
Welche Typen akzeptiert der Compiler für den Parameter ``liste``?
---
## Upper Bounds
Beschränkt den Wildcard Typen nach oben. Dafür wird das Schlüsselwort ``extends`` verwendet.
```java
// Hierarchie Object -> Number -> Integer
// -> Double
class Sortierer {
public void sortiere(List<? extends Number> liste) {
// Ein cleverer Sortieralgorithmus,
// der mit Vergleichoperatoren funktioniert.
}
}
```
Welche Typen akzeptiert der Compiler für den Parameter ``liste``?
---
# Aufgaben
1) Wann benutzt man ``super`` und wann ``extends`` ?
* "Producers Extend, Consumers Super". [Java Guidelines](https://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html)
* ``extends`` erlaubt das Aufrufen von Gettern, ``super`` von Settern