diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2026-10-16 08:53:20 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2026-10-16 08:53:20 +0200 |
| commit | ee86eabbc1ec5c62c71d905f59a96faafa94be95 (patch) | |
| tree | 253df694937279b6dabfbd50c65802e878822d48 | |
| parent | 8e09cf93e80056a06cd5c25411f13ae8e15191d7 (diff) | |
| download | unterricht-ee86eabbc1ec5c62c71d905f59a96faafa94be95.tar.gz unterricht-ee86eabbc1ec5c62c71d905f59a96faafa94be95.zip | |
| -rw-r--r-- | Info/12/Listen/Kompositum/.gitignore | 2 | ||||
| -rw-r--r-- | Info/12/Listen/Kompositum/slides-wiederholung.md | 91 | ||||
| -rw-r--r-- | Info/12/Listen/Kompositum/slides.md | 463 | ||||
| -rw-r--r-- | Info/12/Listen/Trennung_Strukur_Daten/.gitignore | 2 | ||||
| -rw-r--r-- | Info/12/Listen/Trennung_Strukur_Daten/slides-wiederholung.md | 60 | ||||
| -rw-r--r-- | Info/12/Listen/Trennung_Strukur_Daten/slides.md | 174 |
6 files changed, 792 insertions, 0 deletions
diff --git a/Info/12/Listen/Kompositum/.gitignore b/Info/12/Listen/Kompositum/.gitignore new file mode 100644 index 00000000..dd6b8c3d --- /dev/null +++ b/Info/12/Listen/Kompositum/.gitignore @@ -0,0 +1,2 @@ +slides-wiederholung.pdf +slides-wiederholung.pptx diff --git a/Info/12/Listen/Kompositum/slides-wiederholung.md b/Info/12/Listen/Kompositum/slides-wiederholung.md new file mode 100644 index 00000000..68e6c5c2 --- /dev/null +++ b/Info/12/Listen/Kompositum/slides-wiederholung.md @@ -0,0 +1,91 @@ +--- +author: Florian Fischer +theme: metropolis +aspectratio: 169 +--- + +## \faIcon{comments} Wiederholung: Allgemeine Liste \hfill 1/3 + +Nimm Stellung zu folgender Aussage: \vspace{0.25cm} + +> Bei jeder Listen-Implementierung, müssen immer die Klassen für die Daten-Objekte im Code angepasst werden. + +::: {.columns} +:::: {.column width=50%} +```java +class Praxis { + ... + Patient find(...) {} +} +class Knoten { + Knoten next; + Patient daten; + ... +} +``` +:::: + +:::: {.column width=50%} +```java +class CallCenter { + ... + Kunde find(...) {} +} +class Knoten { + Knoten next; + Kunde daten; + ... +} +``` +:::: +::: + +\pause + +\begin{tikzpicture}[overlay, remember picture] + \node[rotate=5,scale=2] at (4, 4.3) {\large \boldred{Falsch}}; +\end{tikzpicture} + +Generics! + +## \faIcon{comments} Wiederholung: Find-Aufruf \hfill 2/3 + +Nimm Stellung zu folgender Aussage: \vspace{0.5cm} + +> Folgende Meldung ist normal, beim Versuch ein Element in einer leeren Liste zu finden. +> `NullPointerException in thread main thread: Auf ein Attribut/eine Methode von null kann nicht zugegriffen werden.` + +\pause + +\begin{tikzpicture}[overlay, remember picture] + \node[rotate=5,scale=2] at (4, 0.3) {\large \boldred{Falsch}}; +\end{tikzpicture} + +\pause + +Eine **NullPointerException** ist ein \boldred{Programmabsturz}, da nicht auf ein nicht vorhandenes Objekt zugegriffen werden kann. + +## \faIcon{comments} Wiederholung: Find \hfill 3/3 + +Nimm Stellung zu folgender Aussage: \vspace{0.5cm} + +> Folgender Code implementiert die rekursive Methode, um einen Eintrag in einer Liste zu finden. + +```java +Entry find(Data tofind) { + if (data == tofind) // Ich bin gesucht + return this.data; + + return next.find(tofind); // Ich frage den Nächsten + } +``` + +\pause + +\begin{tikzpicture}[overlay, remember picture] + \node[rotate=5,scale=2] at (4, 0.3) {\large \boldred{Falsch}}; +\end{tikzpicture} + +\pause + +Wenn es keinen Nächsten mehr gibt, stürzt das Programm ab. diff --git a/Info/12/Listen/Kompositum/slides.md b/Info/12/Listen/Kompositum/slides.md new file mode 100644 index 00000000..cbda020b --- /dev/null +++ b/Info/12/Listen/Kompositum/slides.md @@ -0,0 +1,463 @@ +--- +author: Florian Fischer +theme: metropolis +aspectratio: 169 +--- + +```{.include} +slides-wiederholung.md +``` + +## {.standout} + +Je weniger benötigte Bedingungen, desto einfacher ist der Code und desto weniger Fehler sind möglich. + +## Listenabschluss + +Wie werden wir die Überprüfung des Listenendes los? + +::: {.columns} +:::: {.column width=50%} +```java +if (first == null) ... +``` +:::: + +:::: {.column width=50%} +```java +if (next == null) ... +``` +:::: +::: + +### \faIcon{lightbulb} Idee + +\pause + +Wir nutzen ein besonderes Abschluss-Objekt, das immer am Ende steht. + +## Listenabschluss: Objektdiagramm + +\begin{tikzpicture} + \begin{object}[text width=3cm]{liste}{0,0} + \attribute{anfang} + \end{object} + + \begin{object}[text width=3.5cm]{node1}{-5,-2.5} + \attribute{next} + \attribute{daten} + \end{object} + + \begin{object}[text width=3.5cm]{daten1}{-5,-4.5} + \attribute{inhalt} + \end{object} + + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (d1) at (-5.7, -3.85) {}; + \draw[line width=2pt, draw=blue!80] (d1) edge [bend left=15, -latex] (daten1); + + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (n1) at (-5.8, -3.3) {}; + \draw[line width=2pt, -latex, draw=blue!80] (n1) edge [bend right=15] (-2, -2.75); + + \begin{object}[text width=3.5cm]{node2}{0,-2.5} + \attribute{next} + \attribute{daten} + \end{object} + + \begin{object}[text width=3.5cm]{daten2}{0,-4.5} + \attribute{inhalt} + \end{object} + + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (d2) at (-0.7, -3.85) {}; + \draw[line width=2pt, draw=blue!80] (d2) edge [bend left=15, -latex] (daten2); + + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (n1) at (-0.8, -3.3) {}; + \draw[line width=2pt, -latex, draw=blue!80] (n1) edge [bend right=15] (3, -2.75); + + \begin{object}[fill=white!30!blue, text width=3.5cm]{abschluss}{5,-2.5} + \end{object} + + \only<2->{ + \node[text width=4cm, below=of abschluss] {Jetzt hat jeder Knoten immer einen Nachfolger.}; + } + + % Anfang + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (anfang) at (-1.6, -0.81) {}; + \draw[line width=2pt, -latex, draw=blue!80] (anfang) edge [bend right=25] (-5.1, -2.45); +\end{tikzpicture} + +## Listenabschluss: Klassendiagramm + +::: {.columns} +:::: {.column width=50%} +\begin{tikzpicture} + \node[draw] (list) {\large Liste}; + \node[draw] (leaf) at (-1.5, -2) {\large Abschluss}; + \node[draw] (node) at (1.5, -2) {\large Knoten}; + + \draw[red] (list) edge[sloped, above] node {anfang} (leaf); + \draw[red] (list) edge[sloped, below] node {anfang} (node); + \draw (node.north) |- ($(node.north) + (0, 0.5cm)$) edge[above] node {\textcolor{red}{0,1 < Nachfolger}} ($(node.north) + (2.5cm, 0.5cm)$); + \draw ($(node.north) + (2.5cm, 0.5cm)$) |- (node.east); +\end{tikzpicture} +:::: + +:::: {.column width=50%} +```java +class Liste { + // Kann keinen Abschluss speichern! + Knoten first; + // Kann keinen Knoten speichern! + Abschluss first; +} +``` +:::: +::: + +Ein Referenzattribut kann nicht mehrere Datentypen haben! + +## Listenabschluss: Klassendiagramm Polymorphismus + +### \faIcon{lightbulb} Idee + +Eine gemeinsame Oberklasse! + +::: {.columns} +:::: {.column width=50%} +\begin{tikzpicture} + \node[draw] (list) {\large Liste}; + \node[draw, text width=2.5cm, align=center] (abstract) at (0, -1.5) {\large ListenElement \newline <abstract>}; + \node[draw] (leaf) at (-1.5, -3) {\large Abschluss}; + \node[draw] (node) at (1.5, -3) {\large Knoten}; + + \draw (list) edge[left] node {anfang} (abstract); + \draw[-{Triangle[open, scale=1.5]}] (leaf) -- (abstract); + \draw[-{Triangle[open, scale=1.5]}] (node) -- (abstract); + \draw ($(node.north) + (0.5cm, 0)$) |- (abstract.east); +\end{tikzpicture} +:::: + +:::: {.column width=50%} +```java +class Liste { + // Abschluss oder Knoten + ListenElement first; +} +``` +:::: +::: + +\vspace{0.25cm} +Ein Referenzattribut auf eine Oberklasse kann Objekte aller Unterklassen speichern. + +## Kompositum + +:::{.env .merke} +Das \boldred{Kompositum}, ist ein **Entwurfsmuster** (bewährte Lösung), bei dem primitive Objekte sowie ihre **Komposition** von einer gemeinsamen abstrakten Klasse erben. +Die Vererbung ermöglicht, alle Objekte gleich zu behandeln. +::: + +::: {.columns} +:::: {.column width=50%} +**Beispiel: Liste** `\\[0.25cm]`{=latex} + +\begin{tikzpicture} + \node[draw, text width=2.5cm, align=center] (abstract) at (0, -1.5) {\large Listeneintrag \newline <abstract>}; + \node[draw] (leaf) at (-1.5, -3) {\large Abschluss}; + \node[draw] (node) at (1.5, -3) {\large Eintrag}; + + \draw[-{Triangle[open, scale=1.5]}] (leaf) -- (abstract); + \draw[-{Triangle[open, scale=1.5]}] (node) -- (abstract); + \draw ($(node.north) + (0.5cm, 0)$) |- (abstract.east); +\end{tikzpicture} +:::: + +:::: {.column width=50%} +**Beispiel: Dateisystem** `\\[0.25cm]`{=latex} + +\begin{tikzpicture} + \node[draw, text width=3cm, align=center] (abstract) at (0, -1.5) {\large Verzeichniseintrag \newline <abstract>}; + \node[draw] (leaf) at (-1.5, -3) {\large Datei}; + \node[draw] (node) at (1.5, -3) {\large Verzeichnis}; + + \draw[-{Triangle[open, scale=1.5]}] (leaf) -- (abstract); + \draw[-{Triangle[open, scale=1.5]}] (node) -- (abstract); + \draw ($(node.north) + (0.5cm, 0)$) |- (abstract.east); +\end{tikzpicture} +:::: +::: + + +## Liste mit Kompositum +::: {.columns} +:::: {.column width=40%} +\begin{tikzpicture} +\begin{abstractclass}[text width=5cm]{Listenelement}{0,0} + \operation{naechsterSetzen(Listenelement)} + \operation{naechsterGeben(): Listenelement} + \operation{datenGeben(): Daten} +\end{abstractclass} +\end{tikzpicture} +:::: + +:::: {.column width=60%} +### \faIcon{desktop} Arbeitsauftrag: Neue Liste \hfill 10 min + +Erstelle in einem **neuen** Workspace, die fünf Klassen: + +* `Liste` +* `Listenelement` +* `Eintrag` +* `Abschluss` +* `Daten` + +... mit den dir bekannten Attributen, Methoden und Vererbung. + +\textit{Welche Daten die Liste verwaltet, ist dir überlassen.} + +:::: +::: + +## Liste mit Kompositum: Minimal Version \hfill 1/2 + +```java +class Liste { + Listenelement anfang; +} +abstract class Listenelement { + abstract void naechsterSetzen(ListenElement n); + abstract ListenElement naechsterGeben(); + abstract Daten datenGeben(); +} +class Abschluss extends Listenelement { + void naechsterSetzen(ListenElement n) {} + ListenElement naechsterGeben() { return this; } + Daten datenGeben() { return null; } +} +``` + +## Liste mit Kompositum: Minimal Version \hfill 2/2 + +```java +class Eintrag extends Listenelement { + Listenelement nachfolger; + Daten daten; + + Eintrag(Daten d) { daten = d; } + + void naechsterSetzen(ListenElement n) { nachfolger = n; } + ListenElement naechsterGeben() { return nachfolger; } + Daten datenGeben() { return daten; } +} +class Daten {} +``` + +## {.standout} + +Ist das jetzt wirklich besser? + +## Vergleich: `getLength()` + +::: {.columns align=center} +:::: {.column width=47.5%} +```java +class Liste { // [...] + int getLength() { + if (first == null) return 0; + return first.getLength(); + } +} +class Eintrag { // [...] + int getLength() { + if (next == null) return 0; + return next.getLength() + 1; + } +} +``` +:::: + +:::: {.column width=5%} +\boldred{vs.} +:::: + +:::: {.column width=47.5%} +```java +class Liste { // [...] + int getLength() { + return first.getLength(); + } +} +class Eintrag { // [...] + int getLength() { + return next.getLength() + 1; + } +} +class Abschluss { + int getLength() { + return 0; + } +} +``` +:::: +::: + +## \faIcon{hands-helping} Arbeitsauftrag: Methoden mit Kompositum \hfill 15 min + +Sucht euch zu zweit eine Methode aus. + +* `void vorneEinfuegen(Daten)` +* `void hintenEinfuegen(Daten)` +* `Daten vorneEntfernen()` +* `Daten endeGeben()` +* `void elementEntfernen(Daten)` +* `Daten hintenEntfernen()` + +Erarbeitet einen Algorithmus für eure Liste mit Kompositum: + +1. Visualisiert euren Algorithmus mit Sequenz-/ oder Objektdiagrammen. +2. Implementiert euren Algorithmus in Java oder Pseudocode. + +## \faIcon{desktop} Arbeitsauftrag: Kompositum implementieren + +Implementiere eine Liste mit dem Entwurfsmuster **Kompositum**. + +Deine Liste sollte die folgenden Methoden rekursiv implementieren: + +* `int laengeGeben()` +* `void vorneEinfuegen(Daten)` +* `void hintenEinfuegen(Daten)` +* `Daten vorneEntfernen()` +* `Daten endeGeben()` +* `Daten elementEntfernen(Daten)` +* `Daten hintenEntfernen()` + +### \faIcon{earlybirds} Für Schnelle: + +Implementiere eine allgemeine Liste, die mit Hilfe von **Generics** ohne Code-Änderungen, Objekte beliebiger Klassen verwalten kann. + +## \faIcon{desktop} Implementierung: `int laengeGeben()` + +```java +class Liste { // [...] + int laengeGeben() { + return anfang.getLength(); + } +} +class Eintrag { // [...] + int laengeGeben() { + return nachfolger.getLength() + 1; + } +} +class Abschluss { + int laengeGeben() { + return 0; + } +} +``` + +## Implementierung: `void vorneEinfuegen(daten)` + +```java +class Liste { // [...] + void vorneEinfuegen(daten) { + Eintrag n = new Eintrag(daten); + n.naechsterSetzen(first); + anfang = n; + } +} +class Eintrag { // [...] + void naechsterSetzen(Listeneintrag n) { + nachfolger = n; + } +} +class Abschluss { + void naechsterSetzen(Listeneintrag n) {} +} +``` + +## Implementierung: `void hintenEinfuegen(daten)` + +```java +class Liste { // [...] + void hintenEinfuegen(Daten daten) { + anfang = anfang.hintenEinfuegen(daten); +}} +class Eintrag { // [...] + Listeneintrag hintenEinfuegen(Daten daten) { + nachfolger = nachfolger.hintenEinfuegen(daten); + return this; +}} +class Abschluss { + Listeneintrag hintenEinfuegen(Daten daten) { + Eintrag n = new Eintrag(daten); + n.naechsterSetzen(this); + return n; + } +} +``` + +## Implementierung: `Daten vorneEntfernen()` + +```java +class Liste { // [...] + Daten vorneEntfernen() { + Daten d = anfang.datenGeben(); + anfang = anfang.naechsterGeben(); + return d; + } +} +class Abschluss { + ListenElement naechsterGeben() { return this; } +} +``` + +## Implementierung: `Daten endeGeben()` +```java +class Liste { // [...] + Daten endeGeben() { + return anfang.endeGeben(null); + } +} +class Eintrag { + Daten endeGeben(Daten prev) { + return nachfolger.endeGeben(this.daten); + } +} +class Abschluss { + Daten endeGeben(Daten prev) { + return prev; + } +} +``` + +## Implementierung: `Daten elementEntfernen(daten)` + +```java +class Liste { // [...] + void elementEntfernen(Daten daten) { + anfang.elementEntfernen(daten); + } +} +class Eintrag { + void elementEntfernen(Daten daten) { + if (nachfolger.datenGeben() == daten) { + nachfolger = nachfolger.naechsterGeben(); + } else { + nachfolger.elementEntfernen(daten); + } + } +} +class Abschluss { + Daten elementEntfernen(Daten daten) { } +} +``` + +## Implementierung: `Daten hintenEntfernen()` +```java +class Liste { // [...] + Daten hintenEntfernen() { + Daten ende = anfang.endeGeben(null); + anfang.elementEntfernen(ende); + return ende; + } +} +``` diff --git a/Info/12/Listen/Trennung_Strukur_Daten/.gitignore b/Info/12/Listen/Trennung_Strukur_Daten/.gitignore new file mode 100644 index 00000000..dd6b8c3d --- /dev/null +++ b/Info/12/Listen/Trennung_Strukur_Daten/.gitignore @@ -0,0 +1,2 @@ +slides-wiederholung.pdf +slides-wiederholung.pptx diff --git a/Info/12/Listen/Trennung_Strukur_Daten/slides-wiederholung.md b/Info/12/Listen/Trennung_Strukur_Daten/slides-wiederholung.md new file mode 100644 index 00000000..2b8c0d89 --- /dev/null +++ b/Info/12/Listen/Trennung_Strukur_Daten/slides-wiederholung.md @@ -0,0 +1,60 @@ +--- +author: Florian Fischer +theme: metropolis +aspectratio: 169 +header-includes: + \usepackage{pgf-umlsd} +--- + +## \faIcon{comments} Wiederholung: Sonderfälle \hfill 1/3 + +Nimm Stellung zu folgender Aussage: \vspace{1cm} + +> Alle Sonderfälle: leere Liste, gesuchtes Element ist das Erste/Letzte müssen in der Liste behandelt werden. + +\pause + +\begin{tikzpicture}[overlay, remember picture] + \node[rotate=5,scale=2] at (0.75\textwidth, 2) {\large \textbf{\textcolor{green!80!black}{Korrekt}}}; +\end{tikzpicture} + +## \faIcon{comments} Wiederholung: Sequenzdiagramm \hfill 2/3 {.t} + +Nimm Stellung zu folgender Aussage: \vspace{0.5cm} + +> Das Sequenzdiagramm zeigt einen Ablauf der rekursiven Methode `getLength()`. + +\centering +\begin{sequencediagram} + \newthread{A}{playlist}{} + \newinst[1.5]{B}{s1}{} + \newinst[1.5]{C}{s2}{} + \newinst[1.5]{D}{s3}{} + \begin{call}{A}{?}{B}{null} + \begin{call}{B}{?}{C}{null} + \begin{call}{C}{?}{D}{null} + \end{call} + \end{call} + \end{call} +\end{sequencediagram} + +\pause + +\begin{tikzpicture}[overlay, remember picture] + \node[rotate=5,scale=2] at (5, 3.5) {\large \boldred{Falsch}}; +\end{tikzpicture} + +## \faIcon{comments} Wiederholung: Arten von Listen \hfill 3/3 {.t} + +Nimm Stellung zu folgender Aussage: \vspace{0.75cm} + +> Eine rekursiver Methodenaufruf bedeutet, dass das Objekt eine Methode der eigenen Klasse aufruft. + +\pause + +\begin{tikzpicture}[overlay, remember picture] + \node[rotate=5,scale=2] at (4, 0.3) {\large \boldred{Falsch}}; +\end{tikzpicture} + +\vspace{0.25cm} +> Eine rekursiver Methodenaufruf bedeutet, dass das Objekt die \boldred{gleiche} Methode der Klasse aufruft. diff --git a/Info/12/Listen/Trennung_Strukur_Daten/slides.md b/Info/12/Listen/Trennung_Strukur_Daten/slides.md new file mode 100644 index 00000000..1e24602d --- /dev/null +++ b/Info/12/Listen/Trennung_Strukur_Daten/slides.md @@ -0,0 +1,174 @@ +--- +author: Florian Fischer +theme: metropolis +aspectratio: 169 +header-includes: + \usepackage{pgf-umlsd} +--- + +```{.include} +slides-wiederholung.md +``` + +## \faIcon{chalkboard-teacher} Wiederholung: Die Liste + +\centering +\begin{tikzpicture} + \begin{object}[text width=3cm]{liste}{0,0} + \attribute{anfang} + \attribute{ende} + \end{object} + + \begin{object}[text width=3.5cm]{lied1}{-5,-2.5} + \attribute{name = "foo"} + \attribute{next} + \end{object} + + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (n1) at (-5.8, -3.9) {}; + \draw[line width=2pt, -latex, draw=blue!80] (n1) edge [bend right=15] (-2, -2.75); + + \begin{object}[text width=3.5cm]{lied2}{0,-2.5} + \attribute{name = "bar"} + \attribute{next} + \end{object} + + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (n1) at (-0.8, -3.9) {}; + \draw[line width=2pt, -latex, draw=blue!80] (n1) edge [bend right=15] (3, -2.75); + + \begin{object}[text width=3.5cm]{lied3}{5,-2.5} + \attribute{name = "baz"} + \attribute{next} + \end{object} + + % Anfang + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (anfang) at (-1.6, -0.81) {}; + \draw[line width=2pt, -latex, draw=blue!80] (anfang) edge [bend right=25] (-5.1, -2.45); + + % Ende + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (ende) at (-0.35, -1.4) {}; + \draw[line width=2pt, -latex, draw=blue!80] (ende) edge [bend left=20] (5.1, -2.45); +\end{tikzpicture} + +## {.standout} + +Könnten wir mit unserer Playlist nicht auch Kurzvideos verwalten? + +## Problem + +### Daten und Verwaltung + +In unserer Implementierung ist der Code für die Daten und die Verwaltung der Liste vermischt. + +\pause + +### \faIcon{lightbulb} Trennung von Struktur und Daten + +Wie bekommen wir den Code zur Verwaltung von dem Code für die Daten (Songs, Videos, Kund*innen) getrennt? + +## + +\begin{tikzpicture} + \begin{object}[text width=3cm]{liste}{0,0} + \attribute{anfang} + \attribute{ende} + \end{object} + + \begin{object}[text width=3.5cm]{node1}{-5,-2.5} + \attribute{next} + \attribute{daten} + \end{object} + + \begin{object}[text width=3.5cm]{daten1}{-5,-4.5} + \attribute{inhalt} + \end{object} + + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (d1) at (-5.7, -3.85) {}; + \draw[line width=2pt, draw=blue!80] (d1) edge [bend left=15, -latex] (daten1); + + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (n1) at (-5.8, -3.3) {}; + \draw[line width=2pt, -latex, draw=blue!80] (n1) edge [bend right=15] (-2, -2.75); + + \begin{object}[text width=3.5cm]{node2}{0,-2.5} + \attribute{next} + \attribute{daten} + \end{object} + + \begin{object}[text width=3.5cm]{daten2}{0,-4.5} + \attribute{inhalt} + \end{object} + + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (d2) at (-0.7, -3.85) {}; + \draw[line width=2pt, draw=blue!80] (d2) edge [bend left=15, -latex] (daten2); + + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (n1) at (-0.8, -3.3) {}; + \draw[line width=2pt, -latex, draw=blue!80] (n1) edge [bend right=15] (3, -2.75); + + \begin{object}[text width=3.5cm]{node3}{5,-2.5} + \attribute{next} + \attribute{daten} + \end{object} + + \begin{object}[text width=3.5cm]{daten3}{5,-4.5} + \attribute{inhalt} + \end{object} + + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (d3) at (4.3, -3.85) {}; + \draw[line width=2pt, draw=blue!80] (d3) edge [bend left=15, -latex] (daten3); + + % Anfang + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (anfang) at (-1.6, -0.81) {}; + \draw[line width=2pt, -latex, draw=blue!80] (anfang) edge [bend right=25] (-5.1, -2.45); + + % Ende + \node[fill=black, circle, minimum size=0.005cm, scale=0.5] (ende) at (-0.35, -1.4) {}; + \draw[line width=2pt, -latex, draw=blue!80] (ende) edge [bend left=20] (5.1, -2.45); +\end{tikzpicture} + +## \faIcon{pencil-alt} Arbeitsauftrag: Klassendiagramm \hfill 5min + +Erweitere das Klassendiagramm der Liste, sodass Daten-/ und Listenverwaltung von getrennten Klassen umgesetzt werden. + +### Einfaches Klassendiagramm {.tipp} + +\centering +\begin{tikzpicture} + \node[draw] (list) {\large Liste}; + \node[draw] (song) at (5, 0) {\large Lied}; + + \draw ($(list.east) + (0, 0.1cm)$) edge[above] node {hat als Anfang > 0,1} ($(song.west) + (0, 0.1cm)$); + \draw ($(list.east) - (0, 0.1cm)$) edge[below] node {hat als Ende > 0,1} ($(song.west) - (0, 0.1cm)$); + \draw (song.north) |- ($(song.north) + (0, 0.5cm)$) edge[above] node {0,1 < hat als Nachfolger} ($(song.north) + (3.5cm, 0.5cm)$); + \draw ($(song.north) + (3.5cm, 0.5cm)$) |- (song.east); +\end{tikzpicture} + +## Klassendiagramm mit Trennung zwischen Struktur und Inhalt + +\centering +\begin{tikzpicture} + \node[draw] (list) {\large Liste}; + \node[draw] (node) at (5, 0) {\large ListenElement}; + \node[draw] (song) at (5, -3) {\large Lied}; + + \draw ($(list.east) + (0, 0.1cm)$) edge[above] node {anfang > 0,1} ($(node.west) + (0, 0.1cm)$); + \draw ($(list.east) - (0, 0.1cm)$) edge[below] node {ende > 0,1} ($(node.west) - (0, 0.1cm)$); + \draw (node.north) |- ($(node.north) + (0, 0.5cm)$) edge[above] node {0,1 < nachfolger} ($(node.north) + (3.5cm, 0.5cm)$); + \draw ($(node.north) + (3.5cm, 0.5cm)$) |- (node.east); + + \draw (song.north) edge[above] node[rotate=-90] {verwaltet > 1} (node.south); +\end{tikzpicture} + +## \faIcon{desktop} Arbeitsauftrag: Trennung zwischen Struktur und Inhalt + +1. Dupliziere deinen Listen Workspace +2. Übertrage die Rekursiven Methoden aus der Klasse Song in eine Klasse `ListEntry`. +3. Passe die Methoden der Playlist entsprechend an, dass jeder Song von einem `ListEntry` Objekt verwaltet wird. + +### Beispiel: `void add(Song s)`{.java} {.example} +```java + void add(Song s) { + ListEntry e = new ListEntry(s); // Listenelement für s anlegen + if (last) + last.next = e; // e kommt nach dem aktuell Letzten + last = e; // Das Element wirdam Ende eingefügt + } +``` |
