131 lines
3.1 KiB
Markdown
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
|
|
|