In diesem Konzept für Programmiersprachunterricht wird
angenommen, dass
·
das objektorientierte Paradigma ein wichtigeres
Konzept beim Programmieren ist als die klassischen Sprachelemente (primitive
Typen und Steuerstrukturen)
·
das Paradigma eines Programmierers in hohem Maße
von den ersten Konzepten geprägt wird, die er erlernt.
·
ein didaktisch aufbereitetes Paket geeigneter
fürs Lernen ist als die Standardpakete
Aus diesem Grund werden hier zuerst die objektorientierten
Konzepte ohne die klassischen vermittelt. Das mathematisch-didaktische Prinzip
der Schritt-für-Schritt-Führung wird angewendet: (Möglichst) keine
Sprachelemente werden verwendet, die erst später erläutert werden. Dafür werden
die schon erläuterten Elemente (zur Vertiefung und Einübung) möglichst immer
wieder verwendet. Nicht erklärte Bibliothekselemente werden jedoch von Anfang an
verwendet – eine wichtige Fähigkeit zur Abstraktion
Java als Unterrichtsprache ist für diese Vorgehensweise
geeignet.
Daten, Algorithmen, Kapselung.
Quellprogramm (.java), übersetztes
Programm (.class), statisches (nicht in Java) und dynamisches Binden.
Dokumentation (mit javadoc) und Archive (.jar)
Übersetzen (mit javac) und
Ausführen (mit java oder appletviewer)
Leere Klasse (Definition, Kopf,
leerer Rumpf; reservierte Wörter, Namen; Zeilenkommentar); Fehlermeldung des
Compilers (beim Schreibfehler wie „Class“) und des Interpreters (mit der leeren
Klasse)
Das übliche Hallo-Welt-Programm
enthält viele, erst später zu erläuternde Sprachelemente. Deswegen ist es besser,
mit der leeren Klasse anzufangen – dies ist das einfachste Programm, das
übersetzt werden kann – mit nur wenigen Sprachelementen.
Ausblick: Benutzung von
vorhandenen Klassen: Erweiterung, static-Aufruf, Instanziierung
Leere Erweiterung der leeren
Klasse (Mehrzeilenkommentar; UML-Darstellung der Erweiterung); Compiler-Fehlermeldung
„cannot find symbol“
„Erweiterung“ in Java ist ein
besserer Ausdruck als die übliche „Vererbung“ – selbst wenn hier auch die
Erweiterung leer ist.
(Leere) Erweiterung der leeren
Klasse aus einem Paket; Paket als Namensraum; Bibliothek installieren (.jar,
CLASSPATH)
Die didaktisch aufbereitete
Bibliothek enthält eine leere Klasse, die hier erweitert wird.
Nichtleere Klasse erweitern
à
ausführbar (mit Appletviewer), leeres Applet
Appletviewer erzeugt ein Objekt
der auszuführenden Klasse, deswegen ist er einfacher zu benutzen als der
java-Interpreter. Die zu erweiternde Klasse aus der Bibliothek ist ein leeres
Applet
Klasse HalloWelt erweitern
à
Animation im Applet
Im Gegensatz zum üblichen
Hallo-Welt-Programm wurden hier alle verwendete Sprachelemente schon erklärt;
die Funktionsweise der erweiterten Klasse bleibt jedoch verborgen. Dies ist
wichtig für Abstraktionsfähigkeit – auch in den Standardbibliotheken gibt es
viele verborgene Funktionalitäten.
Mehrfache Erweiterung
Die erweiterte HalloWelt-Klasse
wird nochmals erweitert – an einem UML-Diagramm sollen die Beziehungen erläutert
werden.
Leeres Überschreiben einer Methode
à
Keine Animation sichtbar
Profil einer Methode: Zugriffschutz (public), Ergebnistyp
(void), Name, Parameterliste (leer)
Definition einer Methode: Kopf, Rumpf (leer)
Aufruf einer geerbten Methode
Hinzufügen einer Methode; private Methode; Aufruf der
eigenen Methode
Parameter (vom Typ String)
à
Animation einer Zeichenkette
Profil der aufzurufenden Methode; protected
Mehrere Parameter
Überladen einer Methode
Aufruf einer statischen Methode aus einer anderen Klasse
Import
Dokumentation einer Klasse; Dokumentationskommentare
Editor, Übersetzen, Ausführen vom DOS-Prompt
Erweiterung von
Klassen; Definition und
Aufruf von Methoden
Eine Klasse mit (statischem)
Gedächtnis hat verschiedene Zustände
Klasse mit statischem Konstruktor, die sich im
Appletfenster anzeigt
Methodenaufrufe –
Aufruf einer statischen Methode, die den Zustand verändert und dies anzeigt.
Aufrufsequenzen (Änderung des Zustandes)
Statisches und dynamisches Ende – Unterbrechung einer
Sequenz (return)
Reihenfolgebedingungen, Ausnahmen (beim Fehler in der
Sequenz)
Die Zustandsveränderungen dürfen
nur in einer bestimmten Reihenfolge durchgeführt werden, ansonsten werden
Ausnahmen ausgelöst
Ausnahmebehandlung: try/catch
Ausnahmeverteiler: mehrere catch-Blöcke
Ausnahmedokumentation: throws
Geprüfte und ungeprüfte Ausnahmen
à
Fehler zu Übersetzungs- bzw. Laufzeit
„Unreported Exception“
Auffangen (try/catch) oder Weiterreichen (throws)
Instanziierung einer Klasse (new)
Referenz und Objekt – Objektdiagramm (mit Variablen und
Objekten)
Methodenaufruf für ein Objekt
Zustandsveränderung, ähnlich wie
2.1 für eine Klasse
Mehrere Referenzen, mehrere Objekte in einer Sequenz
Die Standardklasse String
NullPointerException
„Umbiegen“ einer
Referenz, Zuweisung
Verloren gegangenes Objekt, Zwei Referenzen auf ein Objekt
Typprüfung
Lokale und globale Referenzen
Zugriffschutz: public, protected, private, „paketweit“
static-Regel: Klasse.methode() nur wenn static – sonst new
Paket- und Verzeichnisstruktur; Übersetzen und Ausführen
aus dem Wurzelverzeichnis
Geschachtelte Pakete: Benutzung, Vereinbarung
Keine echte Schachtelung von
Paketen, nur des Namensraumes
Dokumentation eines Pakets (mit javadoc)
Anhand der (einfachen) Bibliothek
für den Unterricht soll die Benutzung der Dokumentation antrainiert werden.
Dokumentationsklauseln
Dokumentationskommentar einer Klasse, einer Methode
Dokumentation der Standardpakete
Standardpaket Applet
à
leeres Applet
Überschreiben: start, init, paint
à
Konzept ”Framework“
Der Interpreter (das Framework)
ruft verschiedene Methoden zu verschiedenen Ereignissen auf
Beispielapplet: paint mit drawString
Hauptprogramm main (ohne Erklärung von String[])
Erklärung von java.lang.System.out.println: Paket,
Unterpaket, Klasse, static-Referenz, Methode, Parameter
Jetzt bleibt im klassischen
Hallo-Welt-Programm nur noch String[] unerklärt, sonst ist alles verständlich –
auch die verborgene Funktionalität von println
Implizite Erweiterung: java.lang.Object
Impliziter Import: java.lang.*
Statische Schachtelung (des Programmtextes mit {}) für den
Compiler, Sichtbarkeit
Dynamische Schachtelung (des Ablaufs durch Aufrufe) für den
Interpreter, Lebensdauer
Name (Methode, Referenz) – sichtbar im Block
lokale Variable (Referenz) – lebt im Block
Der Stapel (stack)
Sichtbarkeitsstufen in Java: lokal, privat, paketweit,
geschützt, öffentlich, statisch
Innere Klassen
Blöcke
Geschachteltes try-catch
Rekursive Aufrufe, Abbruch einer Rekursion
formaler Parameter (Definition, lokale Variable), aktueller
Parameter (Aufruf, Ausdruck)
Veränderung von Parametern – Frage: Nach dem Aufruf
veränderter oder ursprünglicher Wert?
Call by
value / Call by reference
Veränderung des Parameterobjekts: Call by reference –
veränderter Wert
Veränderung der Parameterreferenz: Call by value –
ursprünglicher Wert
Variablen: lokal (auf dem Stapel), global (in Objekten auf
der Halde/heap), static (in Klassen)
Mit Hilfe von vorhandenen Klassen
aus der Bibliothek werden ähnliche aber komplexere Klassen implementiert
Objektvariable (globale Referenz)
public Variable (von außen veränderbar – inkonsistenter
Objektszustand)
static = ohne Objekt (der umgebenden Klasse) benutzbar
Regel: in static-Methode nur static
Aufruf einer Objektmethode aus static main
Klassenvariable (static-Referenz)
Objekt- und Klassenvariablen gemischt
Verbreitung von Ausnahmen (über den Stapel weitergereicht)
von Methode zu Methode über die
Aufrufhierarchie
Ausnahme-Strategien: unverändert weiterreichen, auffangen
und behandeln, auffangen und eine andere Ausnahme auslösen, auffangen und
dieselbe Ausnahme auslösen
Ausnahmeobjekt, Ausnahmeklasse vereinbaren
Standard-Ausnahmeklassen: Throwable, Error, Exception, RuntimeException,
NullPointerException
Ausnahmeobjekt versorgen
Vor throw kann das Ausnahmeobjekt
beschrieben, im catch-Block gelesen werden.
static-Block
Jetzt wird die Funktionalität der
Klasse aus 2.1 verständlich, wie sie sich hat anzeigen können
Klassendiagramm (UML), Objektdiagramm
Syntaktische Begriffe, nichtterminale Symbole, terminale
Symbole, Metasymbole
The Java Language Specification
Klassen- und Objektkonstruktor; Überladen des Konstruktors;
Aufruf des Konstruktors
Kopierkonstruktor; Destruktor
Konzepte aus C++:
finalize() in Java
const- und final-Referenzen
Unterschied zwischen const und
final (Objekt bzw. Referenz unveränderbar) – Umsetzung in Java: a) nur im
Kommentar b) immutable Klassen
Strategien: Programmtext kopieren, Klasse instanziieren („einkaufen“),
Klasse erweitern („erben“)
Interface = „unfertige Klasse“
Implementierung eines Interface
Referenz vom Interfacetyp
Mehrfachbeerbung (Erweiterung) von Interfaces
Gleichzeitiges Implementieren und Erweitern
Abstrakte Klasse = „halbfertige Klasse“
Kompatibilität bei Zuweisung (oder Parameterübergabe) von
unterschiedlichen Typen
Aufwärts = von unten nach oben in der Klassenhierarchie –
problemlos, implizit
Abwärts = von oben nach unten in der Klassenhierarchie –
nur explizit
Explizite Typkonvertierung (Casting)
Erfolgreiche Abwärtskompatibilität
Erfolglose Abwärtskompatibilität
à
ClassCastException – hängt vom Objekt ab
Polymorphie – Frage: welche Methode? Antwort: hängt vom
Objekt (nicht von der Referen) ab
Explizites Setzen des Objektzustandes
Die Klasse aus 3.1 exportiert
Aufzählungswerte, die als Parameter der Zustandsveränderungsmethode gegeben
werden können.
Lesen des Objektzustandes mit Hilfe einer Funktion
Funktion = nicht-void-Methode
Aufruf einer Funktion (syntaktisch): rechte Seite einer
Zuweisung, aktueller Parameter eines Aufrufs, Ziel eines Methodenaufrufs
Wirkungsloser Funktionsaufruf – Funktionsergebnis wird
vergessen (in Java leider möglich, von C/C++ übernommen)
Vergleich Prozeduren (void-Methoden) und Funktionen
Implementierung von Funktionen: return
Applet-Funktionen
Beispiel Applet.play
Geschachtelte Funktionsaufrufe
Beispiel Graphics.drawImage
Beispiel Graphics.getImage
Unterschied Applet.init/paint
Um das Applet zu optimieren,
sollte getImage in init, drawImage in paint aufgerufen werden
JApplet, JButton – mit Objektdiagramm
JComboBox
Grafische Oberflächen
Anordnung (layout) der Fensterkomponenten: FlowLayout,
GridLayout, JPanel
Grafik: paint, drawLine, usw.
Mögliche Strategien: Ergänzen vom Programmtext,
Überschreiben leerer Methoden,
Überschreiben abstrakter Methoden, Listener
Registrieren eines Listeners
Interface als Parametertyp: addActionListener
Anonyme Referenz (new als Parameter), Anonyme Klasse
Anonyme Referenzen können benutzt
werden, wenn das Objekt nur einmal benutzt (als Parameter übergeben) wird.
Anonyme Klassen können benutzt werden, wenn sie nur einmal benutzt (instanziiert)
wird.
Anonyme Implementierung (von ActionListener)
Listener: WindowListener, KeyListener, MouseListener, usw.
Mehrzweckklasse
Eine Klasse, die sowohl ein Applet
wie auch ein Listener ist – unsauber aber üblich
Verteilung der Ereignisse: Zwei Buttons, zwei Listener
Menüs: Aufbau, Menüsteuerung
Die swing-Behälterhierarchie
Aufzählungstypen
Arten von Aufzählungstypen: ordnungsfrei, geordnet,
zyklisch
Aufzählungsmethoden – Beispiel: next, previous
boolean
arithmetische Typen: Fließkommatypen (float, double),
Ganzzahltypen (int, char, long, short, byte)
Ein Wert, mehrere Namen: 5.0 und 5.00, 'a' und '\u0097'
char, Sonderliterale (escape sequences)
Ganzzahlliterale: dezimal, oktal, hexadezimal - Syntax
Bruchtypen, Bruchliterale
Diskrete Folge von Bruchzahlen: 7007.0 - 7007.0078125 -
7007.015625
Folge großer Bruchzahlen: 10000000000.0 - 10000001024.0 -
10000002048.0
Sonderwerte: Float/Double.NEGATIVE_INFINITY, usw.
Explizite Konvertierung von primitiven Werten
Genauigkeitsverlust: int i = 1234567890; float f = i;
1234567936.0
Erweiternde und einschränkende Konvertierungen
Interpretation von Operatoren als Methoden (in C++)
Gleichheit, Ungleichheit – Referenz- und Objektgleichheit,
Object.equals
Ordnungsoperatoren (nur für arithmetische Typen)
Logische Operatoren (nur für boolean): diadisch (&, |, ^),
monadisch (!)
Kurzgeschlossene (short cut) Operatoren: && und ||
Boolesche Zuweisungen
Arithmetische Operatoren - Division für Bruch- oder
Ganzzahl
Restberechnung (Modulo)
Arithmetische Zuweisungsoperatoren
Ergebnistyp der Operatoren
Ganzzahl-Überlauf, Bruchüberlauf
Hüllenklassen, Methoden, Werte
java.math.BigDecimal/Integer
Bindungsstärke
Kombination von Operatoren: Operatoren gleicher
Bindungsstärke
Bedingungsoperator
Assoziativität von Operatoren
Sequenz
Ein/Zweiweg-Alternative, Syntax
Mehrweg-Alternative (Fallunterscheidung) –
switch ohne break - Zusammengefaßte Zweige
switch mit enum
foreach-Schleife
Syntax: foreach, for
Ausführung der for-Schleife
for-Schleife ≠ Zählschleife
Zählschleife = spezielle for-Schleife, Kriterien
Leere Schleife, Endlosschleife
Abarbeitung von Zeichenketten
Fakultät
Geschachtelte Zählschleife
Vor- und nachprüfende (kopf- und fußgesteuerte) Schleife
(while, do-while)
Mitteprüfende (rumpfgesteuerte) Schleife (while(true)
if-break)
Fortsetzungsbedingung, Unterbrechungsbedingung
Verwendung der Schleifenarten: Durchwandern einer
Datei/Liste, Endekriterium einlesen
Gleichwertigkeit der bedingungsgesteuerten
Wiederholungsarten
Fakultät rekursiv/iterativ
Fibonacci-Zahlen rekursiv/iterativ
Die Türme von Hanoi
Zeichenketten, mutable Zeichenketten (StringBuffer,
StringBuilder)
char-Reihung
Vereinbarung und Zugriff (schreiben, lesen)
IndexOutOfBoundsException
Bearbeitung von Zeichenketten/Reihungen: Zählen, Sortieren
(bubbleSort)
Reihungsreferenz, Reihungsobjekt
Sortieren von Objekten
Comparable
Kommandozeilenparameter
Variable Parameterzahl – Beispiel:
java.io.PrintStream.format, Formatierungsregeln
Reihungsliteral
Elementtyp als Reihung
à
Mehrdimensionale Reihung, Geschachteltes Rehungsliteral
interface Warteschlange (queue), interface Stapel (stack)
Gruppierung von Collections nach Zugriff (wahlfrei,
gebunden), Elementtyp (fest, beliebig, generisch), Größe (fest, Konstruktor,
dehnbar, dynamisch)
Beispiel für Verwendung Warteschange: Arztpraxis
Implementierung des Ganzzahlstapels als Reihung
Leerer/voller Stapel
eintragen/lesen/entfernen
Objektstapel
Stapel mit Vector
Generischer Stapel
Vorteil: kein ClassCastException beim lesen
Einschränkung des Typparameters: Comparable
Sortieren mit Comparable
Sortieren mit Comparator
Zusicherungen: invariant, assert, requires, ensures
invariant, requires und ensures
gibt es in Eiffel; in Java können sie mit assert nachgebaut werden
Ringpuffer mit %
Testtreiber: Dialog, batch
Programmieren mit Java (4. Auflage) - Vieweg Verlag, 2008