Christian Kohls, Alexander Dobrynin, Florian Leonhard
Programmieren lernen mit Kotlin
Grundlagen, Objektorientierung und fortgeschrittene Konzepte
Inhalt
6
Vorwort
18
1 Einführung
20
1.1 Eine Sprache für viele Plattformen
21
1.2 Deshalb ist Kotlin so besonders
21
1.3 Darauf dürfen Sie sich freuen
22
Teil I: Konzeptioneller Aufbau von Computern und Software
24
2 Komponenten eines Computers
26
2.1 Beliebige Daten als binäre Zahlen
26
2.2 Wie Zahlen in Texte, Bilder und Animationen umgewandelt werden
29
2.3 Zahlen als ausführbarer Code
30
3 Zugriff auf den Speicher
32
3.1 Organisation des Speichers
33
3.2 Daten im Speicher und Datenverarbeitung im Prozessor
34
3.3 Heap und Stack
35
3.4 Programme als Code schreiben statt als Zahlenfolgen
35
4 Interpreter und Compiler
38
4.1 Virtuelle Maschinen, Bytecode und Maschinencode
39
4.2 Kotlin – eine Sprache, viele Plattformen
40
5 Syntax, Semantik und Pragmatik
42
5.1 Syntax
42
5.2 Semantik
43
5.3 Pragmatik
45
6 Eingabe – Verarbeitung – Ausgabe
48
7 Los geht's
50
7.1 Integrierte Entwicklungsumgebungen
51
7.2 Projekt anlegen
53
Teil II: Grundlagen des Programmierens
56
8 Anweisungen und Ausdrücke
58
8.1 Ausdrücke
59
8.1.1 Literale
60
8.1.2 Operationen
61
8.1.3 Variablen und Funktionsaufrufe
63
8.2 Evaluation von Ausdrücken
64
8.2.1 Evaluieren von Operatoren
64
8.2.2 Evaluieren von Funktionen
65
8.2.3 Evaluieren von Variablen
66
8.3 Zusammenspiel von Werten und Typen
67
8.3.1 Typprüfungen durch den Compiler
68
8.3.2 Typen als Bausteine
69
9 Basis-Datentypen
72
9.1 Numerics
73
9.2 Characters und Strings
77
9.3 Booleans
78
9.4 Arrays
79
9.5 Unit
81
9.6 Any
84
9.7 Nothing
85
9.8 Zusammenfassung
86
10 Variablen
88
10.1 Deklaration, Zuweisung und Verwendung
89
10.2 Praxisbeispiel
92
10.2.1 Relevante Informationen extrahieren
92
10.2.2 Das Problem im Code lösen
93
11 Kontrollstrukturen
96
11.1 Fallunterscheidungen mit if
96
11.1.1 if-Anweisung
96
11.1.2 if-Ausdruck
98
11.2 Pattern-Matching mit when
100
11.2.1 Interpretieren von Werten
102
11.2.2 Typüberprüfungen
103
11.2.3 Überprüfen von Wertebereichen
105
11.2.4 Abbilden von langen if-else-Blöcken
107
11.3 Wiederholung von Code mit while-Schleifen
109
11.3.1 Zählen, wie oft etwas passiert
111
11.3.2 Gameloop
112
11.4 Iterieren über Datenstrukturen mit for-Schleifen
113
11.4.1 Iteration mit Arrays
114
11.4.2 Iteration mit Ranges
115
11.4.3 Geht das alles nicht auch mit einer while-Schleife?
116
12 Funktionen
118
12.1 Top-Level- und Member-Functions
118
12.2 Funktionsaufrufe (Applikation)
119
12.3 Syntax
120
12.4 Funktionsdefinition (Deklaration)
122
12.5 Funktionen als Abstraktion
124
12.6 Scoping
125
12.7 Rekursive Funktionen
127
12.7.1 Endlose Rekursion
127
12.7.2 Terminierende Rekursion
128
12.7.3 Rekursion vs. Iteration
129
12.7.4 Von Iteration zur Rekursion
130
12.8 Shadowing von Variablen
131
12.9 Pure Funktionen und Funktionen mit Seiteneffekt
132
12.9.1 Das Schlechte an Seiteneffekten
133
12.9.2 Ohne kommen wir aber auch nicht aus
136
12.9.3 Was denn nun?
137
12.10 Die Ideen hinter Funktionaler Programmierung
138
12.11 Lambdas
139
12.12 Closures
142
12.13 Funktionen höherer Ordnung
143
12.13.1 Funktionen, die Funktionen als Parameter akzeptieren
144
12.13.2 Funktionen, die Funktionen zurückgeben
146
12.14 Zusammenfassung
153
12.15 Das war's
153
Teil III: Objektorientierte Programmierung
154
13 Was sind Objekte?
156
14 Klassen
160
14.1 Eigene Klassen definieren
160
14.2 Konstruktoren
162
14.2.1 Aufgaben des Konstruktors
164
14.2.2 Primärer Konstruktor
164
14.2.3 Parameter im Konstruktor verwenden
165
14.2.4 Initialisierungsblöcke
165
14.2.5 Klassen ohne expliziten Konstruktor
166
14.2.6 Zusätzliche Eigenschaften festlegen
166
14.2.7 Klassen mit sekundären Konstruktoren
167
14.2.8 Default Arguments
168
14.2.9 Named Arguments
169
14.3 Funktionen und Methoden
170
14.3.1 Objekte als Parameter
170
14.3.2 Methoden: Funktionen auf Objekten ausführen
171
14.3.3 Von Funktionen zu Methoden
173
14.4 Datenkapselung
175
14.4.1 Setter und Getter
176
14.4.2 Berechnete Eigenschaften
178
14.4.3 Methoden in Eigenschaften umwandeln
179
14.4.4 Sichtbarkeitsmodifikatoren
180
14.5 Spezielle Klassen
182
14.5.1 Daten-Klassen
182
14.5.2 Enum-Klassen
184
14.5.3 Singuläre Objekte
189
14.6 Verschachtelte Klassen
192
14.6.1 Statische Klassen
193
14.6.2 Lokale Klassen
194
14.6.3 Innere Klassen
195
14.6.4 Anonyme innere Objekte
197
14.7 Klassen und Objekte sind Abstraktionen
197
15 Movie Maker – Ein Simulationsspiel
200
15.1 Überlegungen zur Klassenstruktur
201
15.1.1 Eigenschaften und Methoden von Movie
202
15.1.2 Eigenschaften und Methoden von Director
203
15.1.3 Eigenschaften und Methoden von Actor
204
15.1.4 Genre als Enum
204
15.1.5 Objektstruktur
205
15.2 Von der Skizze zum Programm
206
15.2.1 Movie-Maker-Projekt anlegen
206
15.2.2 Genre implementieren
207
15.2.3 Actor und Director implementieren
207
15.2.4 Erfahrungszuwachs bei Fertigstellung eines Films
209
15.3 Komplexe Objekte zusammensetzen
210
15.3.1 Skills als eine Einheit zusammenfassen
210
15.3.2 Begleit-Objekt für Skills
211
15.3.3 Objektkomposition und Objektaggregation
212
15.3.4 Zusammensetzung der Klasse Movie
214
15.3.5 Film produzieren
216
15.3.6 Ein Objekt für Spieldaten
217
Teil IV: Vererbung und Polymorphie
220
16 Vererbung
222
16.1 Vererbungsbeziehung
223
16.2 Klassenhierarchien
225
16.3 Eigenschaften und Methoden vererben
226
17 Polymorphie
230
17.1 Überschreiben von Methoden
231
17.1.1 Eine Methode unterschiedlich überschreiben
231
17.1.2 Dynamische Bindung
232
17.1.3 Überschreiben eigener Methoden
233
17.1.4 Überladen von Methoden
235
17.2 Typen und Klassen
236
17.2.1 Obertypen und Untertypen
237
17.2.2 Generalisierung und Spezialisierung
238
17.2.3 Typkompatibilität
240
17.2.4 Upcast und Downcast
243
17.2.5 Vorsicht bei der Typinferenz
244
17.2.6 Smart Casts
245
18 Abstrakte Klassen und Schnittstellen
246
18.1 Abstrakte Klassen
246
18.2 Schnittstellen
248
18.2.1 Schnittstellen definieren
249
18.2.2 Schnittstellen implementieren
249
18.2.3 Schnittstellen für polymorphes Verhalten
250
18.2.4 Standardverhalten für Interfaces
253
18.2.5 Mehrere Interfaces implementieren
254
18.3 Alles sind Typen
255
Teil V: Robustheit
258
19 Nullfähigkeit
260
19.1 Nullfähige Typen
260
19.1.1 Typen nullfähig machen
261
19.1.2 Optional ist ein eigener Typ
261
19.2 Sicherer Zugriff auf nullfähige Typen
262
19.2.1 Überprüfen auf null
263
19.2.2 Safe Calls
263
19.2.3 Verkettung von Safe Calls
264
19.3 Nullfähige Typen auflösen
265
19.3.1 Überprüfen mit if-else
265
19.3.2 Der Elvis-Operator rockt
266
19.3.3 Erzwungenes Auflösen
266
20 Exceptions
268
20.1 Sowohl Konzept als auch eine Klasse
268
20.2 Beispiele für Exceptions
269
20.2.1 ArrayIndexOutOfBoundsException
269
20.2.2 ArithmeticException
270
20.3 Exceptions aus der Java-Bibliothek
271
20.4 Exceptions auffangen und behandeln
272
20.4.1 Schreiben in eine Datei
272
20.4.2 Metapher: Balancieren über ein Drahtseil
273
20.5 Exceptions werfen
275
20.6 Exceptions umwandeln
276
20.6.1 Von Exception zu Optional
277
20.6.2 Von Optional zu Exception
278
20.6.3 Exceptions vs. Optionals
278
20.7 Exceptions weiter werfen
279
20.8 Sinn und Zweck von Exceptions
282
21 Movie Maker als Konsolenspiel umsetzen
284
21.1 Die Gameloop
284
21.2 Einen neuen Film produzieren
286
21.3 Statistik anzeigen
289
22 Entwurfsmuster
290
22.1 Das Strategiemuster
291
22.1.1 Im Code verstreute Fallunterscheidungen mit when
291
22.1.2 Probleme des aktuellen Ansatzes
293
22.1.3 Unterschiedliche Strategien für die Ausgabe
294
22.1.4 Nutzen der Strategie
297
22.2 Das Dekorierermuster
297
22.2.1 Probleme des gewählten Ansatzes
299
22.2.2 Dekorierer für Komponenten
300
22.2.3 Umsetzung des Dekorierers
302
22.2.4 Nutzen des Dekorierers
304
22.3 Weitere Entwurfsmuster
305
23 Debugger
306
Teil VI: Datensammlungen und Collections
310
24 Überblick
312
24.1 Pair und Triple
314
24.1.1 Verwendung
314
24.1.2 Syntaktischer Zucker
315
24.1.3 Destructuring
315
24.1.4 Einsatzgebiete
315
24.2 Arrays
316
24.2.1 Direkter Datenzugriff
316
24.2.2 Arrays mit null-Referenzen
317
24.2.3 Arrays mit primitiven Daten
319
24.2.4 Arrays vs. Listen
319
24.3 Listen
320
24.3.1 Unveränderliche Listen
320
24.3.2 Veränderliche Listen
321
24.3.3 List und MutableList sind verwandte Schnittstellen
321
24.4 Sets
322
24.4.1 Sets verwenden
322
24.4.2 Mengen-Operationen
323
24.5 Maps
324
24.5.1 Maps erzeugen
324
24.5.2 Arbeiten mit Maps
325
24.5.3 Maps durchlaufen
326
25 Funktionen höherer Ordnung für Datensammlungen
330
25.1 Unterschiedliche Verarbeitung von Listen
330
25.1.1 Imperative Verarbeitung von Listen
330
25.1.2 Funktionale Verarbeitung von Listen
332
25.1.3 Funktionen als kombinierbare Arbeitsanleitungen
333
25.1.4 Aufbau von Funktionen höherer Ordnung am Beispiel von map
334
25.2 Hilfreiche Funktionen für Datensammlungen
336
25.3 Anwendungsbeispiele für Funktionen höherer Ordnung
338
25.4 Sequenzen
345
25.4.1 Eager Evaluation – viel zu fleißig
345
25.4.2 Lazy Evaluation – Daten bei Bedarf verarbeiten
345
25.4.3 Sequenzen verändern die Reihenfolge
347
25.4.4 Fleißig oder faul – was ist besser?
349
26 Invarianz, Kovarianz und Kontravarianz
350
26.1 Typsicherheit durch Typ-Parameter
350
26.1.1 Invarianz
351
26.1.2 Die Grenzen von Invarianz
352
26.1.3 Kovarianz
352
26.1.4 Kontravarianz
354
26.2 Invarianz, Kovarianz und Kontravarianz im Vergleich
356
27 Listen selbst implementieren
360
27.1 Was ist eine Liste?
360
27.1.1 Unterschiedliche Listen als konkrete Formen
361
27.1.2 Eine Schnittstelle für alle möglichen Listen
361
27.1.3 Typ-Parameter selbst definieren (Generics)
362
27.1.4 Verschiedene Implementierungen derselben Schnittstelle
363
27.2 Implementierung der SimpleList durch Delegation
364
27.3 Implementierung der SimpleList mit Arrays
365
27.3.1 Datenstruktur
365
27.3.2 Direkte Abbildung der Listen-Operationen auf ein Array
365
27.3.3 Listen-Operationen mit aufwendiger Laufzeit bei Arrays
366
28 Verkettete Listen
370
28.1 Basisstruktur der verketteten Liste
371
28.2 Implementierung der verketteten Liste
373
28.3 Umsetzung der Funktionen
373
28.3.1 Einfügen am Anfang einer verketteten Liste
373
28.3.2 Zugriff auf das erste Element der verketteten Liste
375
28.3.3 Zugriff auf das letzte Element der verketteten Liste
375
28.3.4 Allgemeines Schema zum Durchlaufen einer verketteten Liste
377
28.3.5 Elemente der verketteten Liste zählen
377
28.3.6 Zugriff auf das n-te Element
378
28.4 Über alle Listenelemente iterieren
379
28.4.1 Die Schnittstelle Iterable
380
28.4.2 Iterator implementieren
380
28.4.3 Iterator verwenden
381
28.4.4 Interne Iteration
382
29 Testen und Optimieren
384
29.1 Korrektheit von Programmen
384
29.2 Testfälle in JUnit schreiben
385
29.2.1 Assertions
386
29.2.2 Implementierung der Liste testen
386
29.3 Teste zuerst
387
29.4 Klasseninvariante
389
29.4.1 Alternative Implementierung von size() für die verkettete Liste
389
29.4.2 Gewährleistung eines gültigen Zustands
390
30 Optimierung und Laufzeiteffizienz
392
30.1 Laufzeit empirisch ermitteln
392
30.2 Laufzeit theoretisch einschätzen
393
30.3 Die O-Notation
394
30.4 Praktische Beispiele für die O-Notation
395
31 Unveränderliche verkettete Liste
396
31.1 Datenstruktur für die unveränderliche Liste
397
31.1.1 Fallunterscheidung durch dynamische Bindung
397
31.1.2 Explizite Fallunterscheidung innerhalb der Funktion
398
31.1.3 Neue Listen erzeugen statt Liste verändern
398
31.1.4 Hilfsfunktionen über Companion-Objekt bereitstellen
400
31.2 Rekursive Implementierungen
401
31.2.1 map und fold als rekursive Implementierung
401
31.2.2 forEach und Endrekursion
402
Teil VII: Android
404
32 Grundlagen
406
32.1 Erstellen eines Projekts
407
32.2 Aufbau von Android Studio
410
32.3 Funktionsweise einer Android-App
411
32.4 Projektstruktur einer Android-App
416
33 Entwicklung einer Android-App
418
33.1 Integration der Daten
418
33.2 StartActivity erstellen (manuell)
419
33.2.1 Anlegen des Layouts
419
33.2.2 Erstellen der Activity
428
33.2.3 Registrieren der Activity
429
33.3 Persistenz
430
33.3.1 Definition der Schnittstelle
431
33.3.2 Implementierung mit Shared Preferences
432
33.3.3 Zentrales Instanziieren mit Extension Functions
434
33.3.4 Zugriff auf die Datenbankinstanz
434
33.4 CreateMovieActivity erstellen (automatisiert)
435
33.4.1 Erstellen der Activity
435
33.4.2 Starten der Activity
436
33.4.3 Implementieren des Layouts
436
33.4.4 Implementieren der Activity
442
33.5 Ergebnisdialog
448
33.5.1 Erstellen des Layouts
448
33.5.2 Erstellen und Anzeigen des Dialogs
450
33.6 Letzter Feinschliff
451
Teil VIII: Nebenläufigkeit
454
34 Grundlagen
456
34.1 Threads
460
34.1.1 Nicht-determinierter Ablauf
461
34.1.2 Schwergewichtige Threads
462
34.2 Koroutinen (Coroutines)
462
34.2.1 Koroutine vs. Subroutine
463
34.2.2 Coroutines vs. Threads
464
34.3 Zusammenfassung der Konzepte
466
35 Coroutines verwenden
468
35.1 Nebenläufige Begrüßung
469
35.1.1 Koroutine im Global Scope starten
469
35.1.2 Mehrere Koroutinen nebenläufig starten
470
35.1.3 Künstliche Wartezeit einbauen mit sleep
471
35.1.4 Informationen über den aktuellen Thread
472
35.2 Blockieren und Unterbrechen
472
35.2.1 Mehrere Koroutinen innerhalb von runBlocking starten
473
35.2.2 Zusammenspiel von Threads
475
35.3 Arbeit auf Threads verteilen
475
35.4 Jobs
478
35.5 Nebenläufigkeit auf dem main-Thread
479
35.5.1 Zusammenspiel von blockierenden und unterbrechenden Abschnitten
480
35.5.2 Abwechselnde Ausführung
481
35.6 Strukturierte Nebenläufigkeit mit Coroutine Scopes
482
35.7 runBlocking für main
484
35.8 Suspending Functions
485
35.8.1 Unterbrechen und Fortsetzen – Behind the scenes
485
35.8.2 Eigene Suspending Functions schreiben
485
35.8.3 Async
487
35.8.4 Strukturierte Nebenläufigkeit mit Async
489
35.8.5 Auslagern langläufiger Berechnungen
489
35.9 Dispatcher
490
35.9.1 Dispatcher festlegen
490
35.9.2 Wichtige Dispatcher für Android
492
36 Wettlaufbedingungen
494
36.1 Beispiel: Bankkonto
494
36.1.1 Auftreten einer Wettlaufbedingung
496
36.1.2 Unplanbare Wechsel zwischen Threads
496
36.2 Vermeidung von Wettlaufbedingungen
497
36.2.1 Threadsichere Datenstrukturen
497
36.2.2 Thread-Confinement
498
36.2.3 Kritische Abschnitte
501
37 Deadlocks
504
38 Aktoren
508
39 Da geht noch mehr
512
39.1 Infix-Notation
512
39.2 Operatoren überladen
513
39.3 Scope-Funktionen
515
39.3.1 apply-Funktion
515
39.3.2 let-Funktion
516
39.3.3 also-Funktion
517
39.3.4 Unterschiede der Scope-Funktionen
517
39.3.5 with-Funktion
518
39.4 Extension Functions
518
39.5 Weitere Informationsquellen
519
Stichwortverzeichnis
522
© 2009-2024 ciando GmbH