11.03.2014 Aufrufe

Informatik 2 - Einführung

Informatik 2 - Einführung

Informatik 2 - Einführung

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

<strong>Informatik</strong> 2<br />

Einführung in Java und UML<br />

Prof. Dr.-Ing. Holger Vogelsang<br />

holger.vogelsang@hs-karlsruhe.de


Inhaltsverzeichnis<br />

• Roter Faden (4)<br />

• Übersicht (6)<br />

• Übersicht: (8)<br />

• Übersicht (9)<br />

• Arbeitsschritte und Software (14)<br />

• Imperative Aspekte (35)<br />

• Klassen und Objekte (46)<br />

• Fehlererkennung (91)<br />

• Zusicherungen (98)<br />

• Klassen und Objekte (111)<br />

• Überladen von Methoden (121)<br />

• Vererbung (126)<br />

• Überschreiben von Methoden (156)<br />

• Vererbung (183)<br />

• Generische Klassen (189)<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 2


Inhaltsverzeichnis<br />

• Generische Methoden (197)<br />

• Aufzähltypen (202)<br />

• Regeln und Hinweise (208)<br />

• Klassendiagramme (220)<br />

• Fehlerbehandlung mit Ausnahmen (275)<br />

• Pakete (291)<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 3


Roter Faden<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 4


Roter Faden<br />

Übersicht Layouts Ereignisse Widgets<br />

Grafische<br />

Oberflächen<br />

Zeichenoperationen<br />

Grafikwidgets<br />

Effekte,<br />

Animationen<br />

Offene<br />

Punkte<br />

ADTs<br />

Datenstrukturen<br />

in Java<br />

Elementare<br />

Datenstrukturen<br />

Iteratoren<br />

Datenstrukturen<br />

Hashtabellen<br />

Bäume<br />

Graphen<br />

Typinfo.,<br />

I/O<br />

Annotationen<br />

Laufzeittypinfo.<br />

Ein-,<br />

Ausgabe<br />

Entwurf<br />

Prinzipien<br />

Verbindung<br />

von Modulen<br />

Spring<br />

OSGi<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 5


Übersicht<br />

Literatur<br />

Java<br />

• Christian Ullenboom:<br />

<br />

<br />

„Java ist auch eine Insel“, Galileo Computing (auch frei als „Open-Book“ unter<br />

http://openbook.galileocomputing.de/javainsel/)<br />

„Java 7 – Mehr als eine Insel“, Galileo Computing<br />

• D. Ratz, J. Scheffler, D. Seese, J. Wiesenberger: „Grundkurs Programmieren in Java“, Hanser-<br />

Verlag<br />

• R. C. Martin: „Clean Code“, mitp<br />

Objektorientierung allgemein<br />

• B. Lahres, G. Raýman: „Objektorientierte Programmierung“, Galileo Computing (auch frei als<br />

„Open-Book“ unter http://openbook.galileocomputing.de/oop/)<br />

Konfigurationsmanagement und Build-Systeme<br />

• G. Popp: „Konfigurationsmanagement mit Subversion, Maven und Redmine“, dpunkt<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 6


Übersicht<br />

Literatur<br />

UML (Objekt- und Klassendiagramme)<br />

• M. Jeckle, C. Rupp, J. Hahn, B. Zengler, S. Queins: „UML 2 - glasklar“, Hanser-Verlag<br />

• C. Kecher: „UML 2.0 – Das umfassende Handbuch“, Galileo Computing<br />

JavaFX 2<br />

• C. Dea: „JavaFX 2.0: Introduction by Example“, Apress<br />

• J. L. Weaver: „Pro JavaFX 2: A Definitive Guide to Rich Clients with Java Technology“, Apress<br />

• http://docs.oracle.com/javafx/index.html<br />

Datenstrukturen<br />

• G. Saake, K. Sattler: „Datenstrukturen und Algorithmen: Eine Einführung mit Java“, dpunkt<br />

Spring<br />

• C. Walls: „Spring im Einsatz (3. Auflage)“, Hanser-Verlag (deutsch) oder „Spring in Action<br />

(Third Edition)“, Manning (englisch)<br />

OSGi<br />

• B. Weber, P. Baumgartner, O. Braun: „OSGi für Praktiker“, Hanser-Verlag<br />

• G. Wütherich, N. Hartmann, B. Kolb, M. Lübken: „Die OSGI Service Platform“, dpunkt<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 7


Übersicht:<br />

Änderungen zum Sommersemester 2013<br />

• veränderte Reihenfolge<br />

• kleinere Anpassungen<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 8


Übersicht<br />

Hinweise<br />

Markierungen<br />

• Expertenkapitel (nicht klausurrelevant):<br />

• Tafel-/ Rechnerübungen: Längeres Beispiel:<br />

• Pacman-Beispiel:<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 9


Übersicht<br />

Historie im <strong>Informatik</strong>studium<br />

• Bekannt sind aus „<strong>Informatik</strong> 1“:<br />

<br />

<br />

<br />

<br />

<br />

Datentypen<br />

Prozedurale Elemente<br />

einfache Klassen<br />

Arrays<br />

Algorithmen zum Suchen und Sortieren<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 10


Übersicht<br />

Entwicklungsumgebungen<br />

• Java-Entwicklung<br />

<br />

<br />

<br />

Eclipse: http://www.eclipse.org mit zusätzlichen Plugins:<br />

• Findbugs: In Eclipse Help Eclipse Marketplace, „Findbugs“ im Suchfeld<br />

eingeben und „Findbugs Eclipse Plugin” installieren<br />

• Checkstyle zur Überprüfung der Code-Konventionen: In Eclipse Help Eclipse<br />

Marketplace, „Checkstyle“ im Suchfeld eingeben und „Checkstyle Plug-in”<br />

installieren<br />

• SVN Team Provider: In Eclipse Help Eclipse Marketplace, „SVN“ im Suchfeld<br />

eingeben und „Subversive SVN Team Provider” installieren<br />

• SVN Connector: In Eclipse Help Install New Software Add… „SVN-<br />

Connector“ mit der URL „SVN-Connector” Update Site -<br />

http://community.polarion.com/projects/subversive/download/eclipse/3.0/kep<br />

ler-site/ eingeben OK Im Baum links „SVNKit 1.7.10 Implementation”<br />

sowie “SVN Connectors” auswählen und installieren.<br />

Netbeans: http://www.netbeans.org<br />

IntelliJIDEA (freie Community-Version): http://www.jetbrains.com/idea/<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 11


Übersicht<br />

Entwicklungsumgebungen, Durchgängiges Beispiel: Pacman-Klon<br />

• UML:<br />

<br />

<br />

Visual Paradigm, siehe im Ilias unter<br />

https://ilias.hs-karlsruhe.de/repository.php?ref_id=32415&cmd=&rep_frame=1<br />

UML Lab, siehe im Ilias unter<br />

https://ilias.hs-karlsruhe.de/repository.php?ref_id=32415&cmd=&rep_frame=1<br />

• Java und die Datenstrukturen werden anhand eines kleinen Spielfragmentes erläutert, einer<br />

Variation von Pacman:<br />

nur einen Level<br />

verändertes Spielfeld<br />

andere Punktezählung<br />

veränderter interner Aufbau, um alle wichtigen Techniken zeigen zu können<br />

fehlende Spielelemente des Originals<br />

teilweises anderes Verhalten der Figuren<br />

Vektor- statt Pixelgrafik<br />

plattformunabhängige Implementierung mit JavaFX<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 12


Übersicht<br />

Durchgängiges Beispiel: Pacman-Klon<br />

• Spielfeld:<br />

Kirsche (Geister werden für eine gewisse<br />

Zeit ungefährlich und können gefressen<br />

werden)<br />

Tor zur anderen Seite<br />

Geist<br />

Essen<br />

Pacman<br />

• Spielende: Pacman wurde von einem Geist gefressen, oder alle Essensrationen sind von<br />

Pacman gefressen worden.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 13


Arbeitsschritte und Software<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 14


Arbeitsschritte und Software<br />

Motivation<br />

• Bekannt aus <strong>Informatik</strong> 1: Schreiben einfacher Java-Programme<br />

• Wie kann der Quelltext verwaltet werden?<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 15


Arbeitsschritte und Software<br />

Ausführbares Programm<br />

Erzeugen eines ausführbaren Programmes<br />

Quellcode<br />

Pacman.java<br />

Quellcode<br />

Cherry.java<br />

Compiler<br />

Compiler<br />

Bytecode<br />

Pacman.class<br />

Bytecode<br />

Cherry.class<br />

jar<br />

Archiv<br />

(Pacman.jar)<br />

Quellcode<br />

Ghost.java<br />

Compiler<br />

Bytecode<br />

Ghost.class<br />

Bilder/…<br />

Manifest.mf<br />

Manifest-Version: 1.0<br />

Main-Class: de.Main<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 16


Arbeitsschritte und Software<br />

Versionsverwaltung<br />

• Warum sollen die Quelltexte nicht nur im Dateisystem des Entwicklers liegen?<br />

<br />

<br />

Gruppenarbeit:<br />

- Viele Entwickler arbeiten an einem Programm Zugriff auf deren Quelltexte.<br />

- Was haben die anderen Entwickler gemacht oder geändert?<br />

- Was habe ich an dem aktuellen Projekt geschrieben?<br />

Verbesserung der eigenen Arbeitsmöglichkeiten:<br />

- Automatisierte Sicherung: Was passiert bei Zerstörung der lokalen Daten?<br />

- Wiederherstellung eines alten Standes, wenn der neue „kaputtprogrammiert“<br />

wurde „Undo“ zu einer bekannten Version<br />

Wieso sollen mehrere Versionen eines Programmes gepflegt werden?<br />

- Anpassungen für Kunden<br />

- Arbeit an alter Version (Korrekturen) und neuer Version (Erweiterungen)<br />

- Vergleich unterschiedlicher Versionen was hat sich geändert?<br />

Jede neue Version einer Datei erhält eine Versionsnummer.<br />

• Ziel: Speicherung in einem zentralen „Repository“.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 17


Arbeitsschritte und Software<br />

Versionsverwaltung<br />

• Einflüsse während der Programmentwicklung:<br />

viele Entwickler<br />

viele Klassen und<br />

Dokumente<br />

Projekt<br />

viele Versionen<br />

viele unterschiedliche<br />

Arbeitsplätze<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 18


Arbeitsschritte und Software<br />

Versionsverwaltung<br />

• Grafischer Versionsvergleich:<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 19


Arbeitsschritte und Software<br />

Versionsverwaltung<br />

• Lösung: Unterstützung der Entwicklung durch eine Versionsverwaltung. Auswahl:<br />

<br />

<br />

<br />

<br />

RCS/CVS: veraltet<br />

SVN: sehr häufig im Einsatz, ein zentraler Server<br />

Git: manchmal als Nachfolger von SVN gesehen, verteilte Datenhaltung auf mehreren<br />

Servern, oft in Open-Source-Projekten, in Firmen noch selten anzutreffen<br />

Team Foundation Server: reine Microsoft-Lösung<br />

• In <strong>Informatik</strong> 2 und im Softwarelabor: Arbeit mit Subversion (SVN)<br />

• Genauere Einführung z.B. unter http://svnbook.red-bean.com/<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 20


Arbeitsschritte und Software<br />

Versionsverwaltung<br />

• Interne Speicherung im Repository:<br />

<br />

<br />

<br />

Es wird normalerweise nicht jede Version komplett abgelegt.<br />

Statt dessen speichert ein Repository die Unterschiede („Deltas“).<br />

Subversion kennt beide Varianten + komplette Speicherung nach Bedarf.<br />

Version 1 Version 1<br />

Version 2<br />

Version 3<br />

Version 4<br />

Version 5<br />

(aktuell)<br />

als vollständige<br />

Datei<br />

Deltas<br />

(alt)<br />

als vollständige<br />

Datei<br />

Version 2<br />

Version 3<br />

Version 4<br />

Version 5<br />

Rückwärtsdelta:<br />

schnelleres Auslesen<br />

Vorwärtsdelta:<br />

schnelleres Schreiben<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 21


Arbeitsschritte und Software<br />

Versionsverwaltung<br />

• Wichtigste Aktionen für die Arbeit mit Subversion:<br />

<br />

<br />

<br />

<br />

Share: einmalig Projekt im Repository anlegen, eventuell lokales Projekt übergeben<br />

Check out (einmalig für ein Projekt): Projekt aus dem Repository in ein lokales<br />

Verzeichnis kopieren<br />

Commit: lokal erzeugte Änderungen im Repository ablegen<br />

Update: zwischenzeitliche Änderungen im Repository in das lokale Verzeichnis<br />

übernehmen<br />

• Für alle Schritte gibt es Kommandozeilenwerkzeuge sollen hier nicht betrachtet werden.<br />

• Die wichtigsten lassen sich auch mit IDE-Plugins durchführen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 22


Arbeitsschritte und Software<br />

Versionsverwaltung (Installation in Eclipse)<br />

Installation in Eclipse<br />

Unter Help<br />

• Install new Software<br />

• im Baum Collaboration den Subversive<br />

SVN Team Provider auswählen<br />

• Im Menü Window Preferences den<br />

Eintrag Team und dann SVN auswählen.<br />

• Jetzt wird ein SVN-Connector nachinstalliert.<br />

Die Version mit der höchsten Nummer und<br />

reiner Java-Implementierung erfüllt den<br />

Zweck.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 – Versionsverwaltung mit SVN 23


Arbeitsschritte und Software<br />

Versionsverwaltung (Installation in Eclipse)<br />

• Jetzt kann mit Window Open Perspective SVN Repository Exploring die<br />

Ansicht aller SVN-Server angezeigt werden (ist leer).<br />

• Im rechten Fenster SVN Repositories lässt sich durch Rechtsklick mit New <br />

Repository Location ein neuer Server einrichten.<br />

• Für den an der Hochschule müssen Sie folgendes eintragen:<br />

<br />

<br />

<br />

<br />

URL: http://www.iwi.hs-karlsruhe.de/I/svn//<br />

: Ihr IZ-Benutzername<br />

Als Nutzernamen und Password geben Sie Ihren IZ-Account ein.<br />

Save authentication ist auf eigenen Rechnern ganz praktisch, damit Sie sich nicht<br />

immer neu anmelden müssen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 – Versionsverwaltung mit SVN 24


Arbeitsschritte und Software<br />

Versionsverwaltung (Projekt anlegen)<br />

Projekt anlegen<br />

• Wenn das Projekt bisher nur lokal existiert, muss es im Repository angelegt werden.<br />

• Dann können alle anderen Entwickler mit der entsprechenden Berechtigung darauf<br />

zugreifen.<br />

share<br />

ProjektXYZ<br />

Projekt auf dem<br />

lokalen Arbeitsplatz-PC<br />

ProjektXYZ<br />

Repository auf dem<br />

Server mit dem neuen Projekt<br />

http://www.iwi.hs-karlsruhe.de/I/svn//ProjektXYZ/trunk<br />

Repository Root<br />

Projekt-Pfad<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 25


Arbeitsschritte und Software<br />

Versionsverwaltung (Projekt anlegen)<br />

• Ablauf in Eclipse:<br />

<br />

<br />

<br />

<br />

Rechtsklick auf das Projekt<br />

Dann Team und Share Project auswählen.<br />

SVN und im nächsten Dialog Ort des Repositorys auswählen, Simple Mode ist für uns<br />

ausreichend<br />

Kommentar eingeben und auf Finish klicken<br />

• Empfohlener Aufbau eines Projektarchivs (Repository) auf dem Server:<br />

<br />

<br />

<br />

/Projektname/trunk: Hauptentwicklungslinie des Projektes<br />

/Projektname/branches: Alternative Entwicklungen wie z.B. spezielle Anpassungen<br />

für einen Kunden, Wechsel auf neue Technologie, …<br />

/Projektname/tags: Kopie der Hauptentwicklungslinie oder einer Verzweigung zu<br />

einem bestimmten Zeitpunkt.<br />

- Wird z.B. angelegt, wenn eine neue Version an den Kunden ausgeliefert wird. Dann<br />

kann ein Tag mit dem Namen der Version erzeugt wird („Version 1.0“).<br />

- Ein Tag hat keine bestimmte Bedeutung. Er erlaubt aber, bestimmte Versionen mit<br />

einem leicht erkennbaren Namen zu versehen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 26


Arbeitsschritte und Software<br />

Versionsverwaltung (Check out)<br />

Checkout: Daten aus dem Repository auf den lokalen PC kopieren (einmalig)<br />

Check out<br />

Entwickler<br />

lokale Kopie<br />

des Quelltextes<br />

Repository auf dem<br />

Server mit allen Versionen<br />

des Quelltextes +<br />

zusätzlichen Binärdateien<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 27


Arbeitsschritte und Software<br />

Versionsverwaltung (Check out)<br />

• Ablauf in Eclipse:<br />

<br />

<br />

<br />

<br />

Wechsel in die Ansicht SVN Repository Exploring<br />

Rechtsklick auf die gewünschte Version des Projektes<br />

Check Out wählen<br />

Arbeit auf der lokalen Kopie des Projektes<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 28


Arbeitsschritte und Software<br />

Versionsverwaltung (Commit)<br />

Commit: Lokale Änderungen in das Repository übertragen<br />

Änderungen<br />

eintragen,<br />

Konflikte lösen<br />

Entwickler<br />

lokale Kopie<br />

des Quelltextes<br />

Repository auf dem<br />

Server mit allen Versionen<br />

des Quelltextes +<br />

zusätzlichen Binärdateien<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 29


Arbeitsschritte und Software<br />

Versionsverwaltung (Commit)<br />

• Ablauf in Eclipse:<br />

<br />

<br />

<br />

<br />

<br />

<br />

Nach den lokalen Änderungen übertragen die Entwickler die neuen Daten in das<br />

Repository.<br />

Rechtsklick auf das Projekt (z.B. in der Java-Ansicht) oder Rechtsklick auf einzelne<br />

Pakete/Klassen<br />

Dann Team und Commit auswählen.<br />

Die Änderungen sollten unbedingt mit einem Kommentar versehen werden. Der<br />

Kommentar beschreibt, was an der Datei geändert wurde („Fehler xyz behoben“, …).<br />

Nur geänderte Daten werden geschrieben. Sie erhalten dabei eine neue<br />

Versionsnummer (siehe SVN Repository Explorer).<br />

Was passiert, wenn ein anderer Entwickler die Datei bereits verändert hat? Es ist eine<br />

Konfliktbehandlung erforderlich.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 30


Arbeitsschritte und Software<br />

Versionsverwaltung (Commit)<br />

• Konfliktbehandlung:<br />

1. Kopieren-Ändern-Zusammenführen-Modell<br />

- Auschecken einer Version aus dem Projektarchiv: Eine Kopie der Daten wird auf den<br />

Client kopiert.<br />

- Arbeit auf den Client-Dateien<br />

- Einchecken der Änderungen auf den Server: Die Änderungen werden dort<br />

gespeichert, Konflikte müssen behoben werden. Konflikte?<br />

• Was passiert, wenn ein anderer Entwickler dieselbe Datei verändert hat?<br />

• Möglichkeiten:<br />

– Änderungen zusammenführen<br />

– eigene Datei überschreibt die auf dem Server<br />

– eigene Änderungen werden verworfen<br />

– …<br />

• Der SVN-Client hilft beim Zusammenführen beider Versionen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 31


Arbeitsschritte und Software<br />

Versionsverwaltung (Commit)<br />

2. Sperren-Ändern-Entsperren-Modell<br />

- Zur Konfliktvermeidung lassen sich Dateien auf dem Server gegen Änderung<br />

sperren nicht sehr gerne gesehen (insbesondere wenn Sie in den Urlaub fahren<br />

und die Sperre vergessen).<br />

- Bei Binärdateien, die nicht sinnvoll zusammengeführt werden können, ist das<br />

Modell aber durchaus sinnvoll.<br />

- Häufig kann ein Administrator Sperren wieder entfernen.<br />

- Verwendung:<br />

• Rechtsklick auf eine Datei oder ein Verzeichnis, Team und Lock… auswählen.<br />

• Danach die Dateien bearbeiten.<br />

• Abschließend nach einem Commit mit Team und Unlock… wieder freigeben.<br />

• In der Praxis hat sich gezeigt, dass das Kopieren-Ändern-Zusammenführen-Modell wenig<br />

Probleme bereitet: Nicht jeder Entwickler arbeitet gleichzeitig an allen Projektteilen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 32


Arbeitsschritte und Software<br />

Versionsverwaltung (Update)<br />

Update: Zwischenzeitliche Änderungen aus dem Repository übernehmen<br />

Update<br />

Entwickler<br />

lokale Kopie<br />

des Quelltextes<br />

Repository auf dem<br />

Server mit allen Versionen<br />

des Quelltextes +<br />

zusätzlichen Binärdateien<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 33


Arbeitsschritte und Software<br />

Versionsverwaltung (Update)<br />

• Während der Arbeit oder nach einer Pause haben andere Entwickler eventuell neue<br />

Versionen im Repository abgelegt.<br />

• Vor einer Änderungen in der eigenen lokalen Kopie sollte sie aktualisiert werden, damit nicht<br />

ein alter Stand verändert wird.<br />

• Ablauf in Eclipse:<br />

Rechtsklick auf ein Paket, eine Klasse, eine Ressource oder das Projekt, dann Team und<br />

Synchronize with Repository auswählen.<br />

Eine weitere Ansicht zeigt die Änderungen, die übernommen werden können.<br />

• Weitere Funktionen: siehe weiterführende Literatur (insbes. „Merge“ verschiedene<br />

Entwicklungszweige und Kollisionsbehandlung beim „Commit“)<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 34


Imperative Aspekte<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 35


Imperative Aspekte<br />

Motivation<br />

• Wie sollte der Quelltext formatiert sein?<br />

• Zusammenhang zwischen primitiven Datentypen und Klassen<br />

• Wie kann die falsche Verwendung von Funktionen und Algorithmen zur Laufzeit<br />

erkannt werden?<br />

• Als bekannt vorausgesetzt: Schleifen, Abfragen, lokale Variable<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 36


Imperative Aspekte<br />

Formatierung des Quelltextes<br />

Hinweise zur Formatierung<br />

• Der Compiler ignoriert jegliche Formatierung des Quelltextes.<br />

• Ein Programmierer benötigt dringend eine gut lesbare Struktur!<br />

• Beispiel:<br />

public V(){for(int i=0;i


Imperative Aspekte<br />

Einige Regeln zur Formatierung des Quelltextes<br />

Einige ganz einfache Regeln<br />

• Anfangs- und Endklammern eines Blocks immer in dieselbe Spalte setzen oder die<br />

Endklammer an das Ende der Zeile davor.<br />

• Den Inhalt eines Blockes immer entweder um einen Tabulator oder eine gleiche Anzahl von<br />

Leerzeichen einrücken.<br />

• Beispiel:<br />

for (int i = 0; i < 10; i++) {<br />

Blockinhalt<br />

}<br />

• Selbsterklärende Variablen- und Methodennamen verwenden.<br />

• Großzügig Leerzeilen zwischen verschiedene Blöcke einfügen, um logisch getrennte Einheiten<br />

optisch anzuzeigen.<br />

• Großzügig Leerzeichen zur Formatierung einfügen.<br />

• Reihenfolgen der Operatoren durch Klammerungen optisch hervorheben.<br />

• Sinnvolle Kommentare verwenden (nicht einfach: Hier wird x erhöht.)<br />

• Siehe auch: http://www.ioccc.org/ (The International Obfuscated C Code Contest)<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 38


Imperative Aspekte<br />

Konstanten: String und Zeichen<br />

String- und Zeichenkonstanten im Unicode-Format<br />

• Zeichenkonstanten: char, z.B.: 'A', numerischer Wert = 65<br />

• Stringkonstanten: Folge von char, z.B.: "ABD".<br />

Beispiele<br />

Zeichen Bedeutung Num. Wert<br />

A Großbuchstabe A 65<br />

Leerzeichen 32<br />

0 Ziffer 0 48<br />

\xdd dd = Num. Wert eines Zeichens im Hexadezimalsystem \xdd<br />

\ddd Eine Folge von 1, 2 oder 3 oktalen Ziffern \ddd<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 39


Imperative Aspekte<br />

Konstanten: String und Zeichen<br />

Vordefinierte Sonderzeichen<br />

Zeichen Bedeutung Num. Wert<br />

\\ Das Zeichen \ selbst (ein Backslash). 92<br />

\" Das Zeichen " 34<br />

\' Das Zeichen ' 39<br />

\b Rückwärts Löschen, Backspace, BS 8<br />

\f Seitenvorschub, form-feed, FF 12<br />

\n Zeilenvorschub, new line oder line feed, LF 10<br />

\r Wagenrücklauf, carriage return, CR 13<br />

\t Horizontaler Tabulator, HT 9<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 40


Imperative Aspekte<br />

Konstanten: String und Zeichen (Pacman-Beispiel)<br />

• Beschreibung des Spielfeldes im Quelltext durch eine Zeichenkette<br />

• Die Zeichenkette wird später eingelesen, um die einzelnen Objekte zu erzeugen.<br />

String[] fieldLayout = {<br />

".....*.........*.....",<br />

"o***.*.*******.*.***o",<br />

"..........C..........",<br />

"**.*.****.*.****.*.**",<br />

" *.*.*....*.*....*.* ",<br />

"**.*.****.*.****.*.**",<br />

"E .*......*......*. E",<br />

"**.*** ******* ***.**",<br />

" *. 0 .* ",<br />

" *.*** ###-### ***.* ",<br />

" *.* #2 1 3# *.* ",<br />

"**.* * ###-### * *.**",<br />

"E . * C * . E",<br />

"**.****** * ******.**",<br />

".*..... * .....*.",<br />

".*.***.*******.***.*.",<br />

"..........P..........",<br />

// usw.<br />

};<br />

C<br />

Zeichen<br />

Bedeutung des Feldes<br />

enthält eine Kirsche (Cherry)<br />

* kann nicht betreten werden<br />

0 - 3 Nummer des Geistes<br />

E<br />

mit Ausgang (Exit) auf die andere Seite<br />

# ist Gefängnisumrandung (entspricht hier<br />

'*')<br />

o<br />

mit Energiepaket (nicht verwendet)<br />

P mit Pacman<br />

Ohne Angabe: leeres Feld<br />

. mit Essensportion<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 41


Imperative Aspekte<br />

Konstanten: String und Zeichen (Pacman-Beispiel)<br />

String[] fieldLayout = {<br />

".....*.........*.....",<br />

"o***.*.*******.*.***o",<br />

"..........C..........",<br />

"**.*.****.*.****.*.**",<br />

" *.*.*....*.*....*.* ",<br />

"**.*.****.*.****.*.**",<br />

"E .*......*......*. E",<br />

"**.*** ******* ***.**",<br />

" *. 0 .* ",<br />

" *.*** ###-### ***.* ",<br />

" *.* #2 1 3# *.* ",<br />

"**.* * ###-### * *.**",<br />

"E . * C * . E",<br />

"**.****** * ******.**",<br />

".*..... * .....*.",<br />

".*.***.*******.***.*.",<br />

"..........P..........",<br />

".***.****.*.****.***.",<br />

// usw.<br />

};<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 42


Imperative Aspekte<br />

Parameterübergabe per Wert bei primitiven Datentypen<br />

Parameterübergabe per Wert (Call by Value)<br />

• Werte primitiver Datentypen werden immer per Wert übergeben. Es wird eine lokale Kopie<br />

erzeugt. Änderungen am Wert innerhalb einer Methode wirken nicht nach außen.<br />

Beispiel:<br />

public void doSomething(int xx){<br />

xx = 2;<br />

}<br />

public int doSomethingElse(){<br />

int x = 21;<br />

doSomething(x);<br />

System.out.println(x);<br />

return 0;<br />

}<br />

Ausgabe: 21<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 43


Imperative Aspekte<br />

Parameterübergabe per Referenz bei Objekten<br />

Parameterübergabe per Referenz (Call by Reference)<br />

• Objekte werden immer per Referenzen übergeben werden. Damit sind Änderungen nach<br />

außen sichtbar. Beispiel:<br />

public void doSomething(Bruch br){<br />

br.setZaehler(42);<br />

}<br />

public int doSomethingElse(){<br />

Bruch br = new Bruch(21, 3);<br />

doSomething(br);<br />

System.out.println(br.getZaehler());<br />

return 0;<br />

}<br />

Ausgabe: 42<br />

• Zusatznutzen einer Referenzübergabe: Das Anlegen einer Kopie kann zeitaufwändig sein.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 44


Imperative Aspekte<br />

Ergebnisrückgabe<br />

• Es gilt dasselbe wie bei Übergaben:<br />

<br />

<br />

Werte primitiver Datentypen werden als Kopie und<br />

Objekte per Referenz zurückgegeben.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 45


Klassen und Objekte<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Typinformationen<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassendiagramme<br />

Ein-,<br />

Ausgabe<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Annotationen<br />

Überladen<br />

Laufzeittypinfo.<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 46


Klassen und Objekte<br />

Objekte<br />

Einige Objekte im Pacman-Spiel<br />

• Pacman<br />

• die Geister 1 bis 4<br />

• einzelne Kirschen<br />

• das Spielfeld<br />

Einige Eigenschaften von Objekten (Zustandsinformationen)<br />

• Pacman: bewegt sich nach oben, öffnet den Mund<br />

• Geist 1: ist gefährlich, befindet sich auf Zelle (2,3), bewegt sich nach unten und hat eine<br />

gewisse „Intelligenz“<br />

• Geist 2: ist gefährlich, befindet sich auf Zelle (12,5), bewegt sich nach links und hat ebenso<br />

eine gewisse „Intelligenz“<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 47


Klassen und Objekte<br />

Objekte<br />

Objekte kommunizieren (Verhalten)<br />

• Das Spielfeld sagt zu Pacman: „Bewege Dich nach oben“<br />

Quellobjekt (Spielfeld) schickt dem Ziel (Pacman) eine Nachricht.<br />

Objekte unterscheiden sich (Identität)<br />

• Geist 1 ist nicht Geist 2.<br />

• Alle Objekte sind eindeutig unterscheidbar!<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 48


Klassen und Objekte<br />

Objekte<br />

Definition: Objekt<br />

Ein Objekt ist eine konkret vorhandene Einheit mit folgenden Merkmalen:<br />

<br />

<br />

<br />

<br />

Identität: Alle Objekte lassen sich eindeutig unterscheiden (z.B. durch die Referenz).<br />

Zustand (Daten):<br />

- Alle Attributwerte des Objektes. Der Typ der Attribute wird durch die Klasse<br />

festgelegt.<br />

- Der Zustand ist nur durch das Objekt selbst veränder- und sichtbar, nicht aber von<br />

außen.<br />

- Beziehungen zu anderen Objekten.<br />

Eigenschaften (Properties):<br />

- Sie können von außen abgefragt werden.<br />

- Sie werden unter Umständen aus Daten berechnet, sind aber selbst keine Daten<br />

(z.B. Alter = Datum - Geburtsdatum).<br />

Verhalten: Festgelegt durch Methoden der Klasse des Objektes.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 49


Klassen und Objekte<br />

Objekte<br />

Vereinfachte Darstellung von Objekten in UML:<br />

geist1: Geist<br />

x = 2<br />

y = 3<br />

IQ = 70<br />

direction = DOWN<br />

/nextX<br />

Name des Objektes<br />

und Name der Klasse<br />

Zustand (Daten)<br />

Eigenschaften (Properties)<br />

{if (direction == DOWN)<br />

nextX = max(x-1, 0)}<br />

Einschränkungen<br />

(Constraints)<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 50


Klassen und Objekte<br />

Klassen<br />

Objekte haben Gemeinsamkeiten<br />

• Alle Geister haben Daten x, y und direction mit entsprechenden Werten und eine<br />

berechnete neue X-Position direction hat bei jedem Geist denselben Typ.<br />

Zusammenfassung von Objekten gleicher Eigenschaften zu Klassen<br />

• Geist 1 und 2 gehören zur Klasse Ghost:<br />

<br />

<br />

gleiche Attribut- und Eigenschaftstypen<br />

gleiches Verhalten<br />

Definition: Klasse (im Implementierungsmodell)<br />

Eine Klasse ist die Definition der Attribut-, Eigenschaftstypen und Operationen einer Menge<br />

von Objekten.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 51


Klassen und Objekte<br />

Klassen<br />

Definition: Attribut (auch Instanzvariable genannt)<br />

• Ein Attribut ist eine Eigenschaft eines Objektes, die von außen abgefragt werden kann.<br />

• Es kann ein Datenelement oder ein berechneter Wert (=abgeleitetes Attribut) sein.<br />

• Ein Attribut kommt in allen Objekten der Klasse vor.<br />

• Der Wert des Attributs kann in den Objekten unterschiedlich ausfallen.<br />

• Ein Attribut kann nicht ohne das zugehörige Objekt leben.<br />

• Ein Attribut hat keine Identität.<br />

In der Vorlesung wird der Begriff „Attribut“ immer für ein Datenelement verwendet.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 52


Klassen und Objekte<br />

Klassen<br />

Definition: Operation<br />

• Eine Operation legt fest, welche Funktionalität ein Objekt bereitstellt.<br />

• Unterstützt ein Objekt eine bestimmte Operation, so sichert es einem Aufrufer zu, dass es bei<br />

einem Aufruf die Operation ausführen wird.<br />

• Durch die Operation wird die Syntax des Aufrufs vorgegeben (Typen der Parameterwerte).<br />

• Die Operation gibt Zusicherungen darüber, welche Resultate die Operation haben wird.<br />

• Die Operation beinhaltet keine Implementierung. Sie beschreibt „lediglich“ Schnittstelle<br />

(Signatur) und Zusicherung nach außen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 53


Klassen und Objekte<br />

Klassen<br />

Definition: Methode<br />

• Eine Methode ist die konkrete Implementierung einer Operation.<br />

• Während Operationen die Funktionalität nur abstrakt definieren, sind Methoden für die<br />

Realisierung dieser Funktionalität zuständig.<br />

• In der Vorlesung wird die strenge Kategorisierung von Methode und Operation nicht immer<br />

aufrechterhalten.<br />

• Hier wird häufig „Methode“ als Synonym für beide Begriffe verwendet.<br />

• „Operation“ wird dort verwendet, wo es speziell auf den reinen Signaturcharakter ankommt.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 54


Klassen und Objekte<br />

Klassen und Objekte (Pacman-Beispiel)<br />

Beispiel zu Klasse und Objekt (unvollständiges Beispiel)<br />

Klassenname<br />

Attribute<br />

Operationen<br />

Ghost<br />

-x: int<br />

-y: int<br />

-direction: Direction<br />

+setX(x: int)<br />

+setY(y: int)<br />

+paint(p: JPanel,<br />

cellWidth: int,<br />

cellHeight: int)<br />

geist1: Ghost<br />

x = 2<br />

y = 3<br />

direction = UP<br />

Attributwerte<br />

geist2: Ghost<br />

x = 12<br />

y = 3<br />

direction = DOWN<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 55


Klassen und Objekte<br />

Objektorientierte Sichtweise<br />

Idee der Kapselung (Information hiding)<br />

• Die Implementierung der Datenstrukturen und Algorithmen innerhalb einer Klasse wird<br />

gegenüber den Aufrufern „versteckt“. Sie kann nach außen unsichtbar verändert werden.<br />

Methoden<br />

Attribute<br />

Aufruf<br />

Objekt<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 56


Klassen und Objekte<br />

Objektorientierte Sichtweise (Pacman-Beispiel)<br />

Beispiel: Kapselung des Geistes in einer Klasse<br />

paint<br />

x<br />

setX<br />

direction<br />

Ghost<br />

y<br />

setY<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 57


Klassen und Objekte<br />

Objektorientierte Sichtweise<br />

• Vorteile der Kapselung:<br />

<br />

<br />

Interne Zustände und deren Abhängigkeiten bleiben nach außen verborgen Leichtere<br />

Konsistenzhaltung der Daten.<br />

Bei Zustandsänderung müssen häufig noch andere Operationen ausgeführt werden.<br />

Beispiel:<br />

- Im Pacman-Spiel wird die Farbe einer Figur geändert. Die Farbe ist ein Attribut der<br />

Figur.<br />

- Danach muss die Figur neu gezeichnet werden.<br />

- Bei sauberer Kapselung wird durch die Farbänderung automatisch das Neuzeichnen<br />

ausgelöst.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 58


Klassen und Objekte<br />

Objektorientierte Sichtweise<br />

• Funktioniert die Kapselung immer? Beispiel:<br />

<br />

<br />

<br />

Im Pacman-Spiel werden einzelne Figuren auf dem Spielfeld platziert.<br />

Die Figuren haben Attribute wie „Farbe“, „Bewegungsrichtung“ und „Position“.<br />

Der aktuelle Spielstand soll auf Festplatte gespeichert werden Zugriff auf die Attribute<br />

zum Speichern notwendig.<br />

• Konsequenz:<br />

<br />

<br />

<br />

<br />

<br />

Jede Figur müsste selbst speichern Verteilung der Speicherfunktionalität auf viele<br />

Klassen sehr unschön.<br />

Eine Klasse speichert, muss aber auf die privaten Attribute der Figuren zugreifen <br />

Aushebelung der Kapselung?<br />

Nein: Kapselung ist immer auf einen Aufgabenbereich beschränkt.<br />

Speicherung ist eine andere Aufgabe, darf also auf die privaten Daten zugreifen.<br />

Das gilt aber nicht für Klassen, die für das Zeichnen verwendet werden.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 59


Klassen und Objekte<br />

Zugriffsrechte<br />

Zugriffsrechte<br />

• private: Auf private Attribute oder Methoden dürfen nur Methoden der eigenen Klasse<br />

zugreifen.<br />

• public: Auf öffentliche Attribute und Methoden dürfen alle Methoden anderer Klassen<br />

zugreifen.<br />

• protected: für Vererbung (kommt später ...)<br />

• : Paketrecht (kommt später …)<br />

• Die Rechte gelten auf Klassenebene: Ein Objekt einer Klasse darf auf private Attribute eines<br />

anderen Objektes derselben Klasse zugreifen!<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 60


Klassen und Objekte<br />

Klassen in UML<br />

Vereinfachte Darstellung von Klassen in UML:<br />

- x: int<br />

- y: int<br />

- count: int<br />

Ghost<br />

Klassenname<br />

Attribute<br />

statisches Attribut<br />

+ paint(p: JPanel, x: int, y: int)<br />

+ setX(x: int)<br />

+ setY(y: int)<br />

Operationen<br />

Attribut (Angaben in eckigen Klammern sind optional):<br />

[Sichtbarkeit][/]Name[:Typ][Multiplizität][=Vorgabewert] [{Eigenschaft}]<br />

• Sichtbarkeit/Zugriffsrecht:<br />

<br />

<br />

<br />

<br />

#: geschützt (protected)<br />

-: privat (private)<br />

+: öffentlich (public)<br />

~: Paket (package)<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 61


Klassen und Objekte<br />

Klassen in UML<br />

• /: Das Attribut ist eine Eigenschaft. Es wird berechnet und muss somit nicht gespeichert<br />

werden.<br />

• Name: Name des Attributs. Aufgrund von Einschränkungen vieler Programmiersprachen sollte<br />

man auf Umlaute usw. verzichten.<br />

• :Typ: Typ des Attributs<br />

• Multiplizität: Anzahl Ausprägungen des Attributs<br />

kann als Array betrachtet werden<br />

Angaben sind minimale und maximale Anzahl oder die genaue Anzahl:<br />

- [2]: exakt zwei Werte<br />

- [1..2]: ein oder zwei Werte<br />

- [1..*]: mindestens ein Wert bis beliebig viele Werte<br />

- [0..*] bzw. [*]: beliebig viele Werte<br />

• =Vorgabewert: Initialwert für das Attribut<br />

muss zum Typ des Attributs passen<br />

bei Multiplizität größer als 1: Aufzählung in der Form {1, 2, 3, 4}<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 62


Klassen und Objekte<br />

Klassen in UML<br />

• {Eigenschaft}: besondere Merkmale des Attributs (Auswahl)<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

{readOnly}: Der Wert darf nach der Initialisierung nicht mehr verändert werden (eine<br />

Konstante).<br />

{subsets }: Der Wert ist eine Untermenge der Werte, die in dem<br />

Attribut erlaubt sind.<br />

{union}: Vereinigung aller Attributwerte, die mit subsets spezifiziert wurden.<br />

{redefines }: Redefiniert ein Attribut seiner Basisklasse<br />

{ordered}: Die Attributwerte müssen geordnet vorliegen. Duplikate sind nicht erlaubt.<br />

{bag}: Die Attributwerte müssen nicht geordnet vorliegen. Duplikate sind erlaubt.<br />

{seq} bzw. {sequence}: Die Attributwerte müssen geordnet vorliegen. Duplikate sind<br />

erlaubt.<br />

{unique}: Die Attributwerte müssen nicht geordnet vorliegen. Duplikate sind nicht<br />

erlaubt.<br />

{composite}: Das Attribut wird durch Komposition an die Klasse gebunden. Es ist so<br />

selbst für die Zerstörung seines Inhalts verantwortlich.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 63


Klassen und Objekte<br />

Klassen in UML<br />

Operation (Angaben in eckigen Klammern sind optional):<br />

[Sichtbarkeit]Name([Parameterliste])[:Rückgabetyp] [{Eigenschaft}]<br />

• Sichtbarkeit/Zugriffsrecht: wie bei Attributen<br />

• Name: wie bei Attributen<br />

• Parameterliste mit dem folgenden Aufbau:<br />

[Übergabemodus] Name :Typ [Multiplizität][=Vorgabewert][{Eigenschaft}]<br />

<br />

Übergabemodus (unvollständig):<br />

- in: Der Parameter wird von der Operation nur gelesen. Fehlt der Modus, so wird in<br />

angenommen. In Java nur für primitive Datentypen möglich.<br />

- out: Der Parameter wird von der Operation nur geschrieben.<br />

Umsetzungsmöglichkeit in Java nur für Objekte (Besonderheit String <br />

StringBuffer, …)<br />

- inout: Der Parameter wird von der Operation gelesen und geschrieben.<br />

Umsetzungsmöglichkeit in Java nur für Objekte.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 64


Klassen und Objekte<br />

Klassen in UML<br />

<br />

<br />

Name: Name des Parameters<br />

:Typ: Typ des Parameters<br />

Multiplizität: Anzahl Ausprägungen des Parameters, die übergeben werden. Die<br />

Angaben erfolgen wie bei Attributen. Umsetzungsmöglichkeit in Java: Arrays<br />

=Vorgabewert: Wert, den der Parameter erhält, wenn er nicht übergeben wird.<br />

Umsetzung in Java nicht direkt möglich.<br />

{Eigenschaft}: siehe Attribute<br />

• :Rückgabetyp: Typ des Rückgabewertes, fehlt dieser, so wird void angenommen. Die<br />

Angabe void ist nicht erlaubt.<br />

• {Eigenschaft}: Angabe spezieller Merkmale des Rückgabetyps, siehe Attribute.<br />

• Und was ist mit Ausnahmen (Exceptions)? UML kennt sie nicht. Ausweg in Form eines<br />

Eigenschaftswertes (Tagged Value):<br />

{raisedException=NameDerAusnahme}<br />

Andere, eigene Eigenschaftswerte sind auch erlaubt sinnvoll bei MDA.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 65


Klassen und Objekte<br />

Klassen in UML (Pacman-Beispiel)<br />

• Klasse für eine Zelle des Spielfeldes (unvollständig):<br />

- border: int<br />

- food: boolean<br />

- exit: boolean<br />

Cell<br />

+ paint(panel: JPanel, x: int, y: int)<br />

+ isFood(): boolean<br />

+ isExit(): boolean<br />

+ getBorder(): int<br />

• Weitere Klassen kommen erst später, weil sie Vererbung bzw. Beziehungen zwischen Klassen<br />

benötigen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 66


Klassen und Objekte<br />

Klassen allgemein<br />

Typen von Klassen<br />

• Statisches Typsystem (C++, C#, Java, …):<br />

<br />

<br />

Der Typ von Variablen und Parametern wird im Quelltext festgelegt.<br />

Vorteile:<br />

- bessere Optimierung durch den Compiler möglich<br />

- saubere Programmstruktur, da Typen direkt im Quelltext ersichtlich sind<br />

- gute Unterstützung durch IDEs, da diese die Variablentypen erkennen<br />

- frühzeitige Fehlererkennung durch den Compiler<br />

• Dynamisches Typsystem (z.B. JavaScript):<br />

<br />

<br />

<br />

Variablen können beliebige Daten aufnehmen.<br />

Der Variablentyp steht erst zur Laufzeit fest.<br />

Vorteile:<br />

- Werte können von beliebigem Typ sein automatische Konvertierung<br />

- Ducktyping: Wenn es watschelt wie eine Ente, wenn es schwimmt wie eine Ente,<br />

wenn es quakt wie eine Ente, dann behandeln wir es wie eine Ente.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 67


Klassen und Objekte<br />

Klassen allgemein<br />

Stark und schwach typisierte Programmiersprachen<br />

• Stark typisierte Sprache: Überwacht das Erstellen und den Zugriff auf alle Objekte so, dass<br />

sichergestellt ist, dass Referenzen/Zeiger immer auf Objekte verweisen, die auch die<br />

Spezifikation des Typs erfüllen, der für die Variable deklariert ist. Beispiel: Java<br />

• Schwach typisierte Sprachen: Zeiger können auf Objekte verweisen, ohne dass das Objekt<br />

notwendigerweise die Spezifikation des Typs der Variablen erfüllt. Beispiel: C++<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 68


Klassen und Objekte<br />

Klassensyntax in Java<br />

Syntax von Klassen in Java<br />

• Eine Klasse kapselt Attribute, Operationen und eventuell Operatoren als eine Einheit.<br />

• Beispiel zu Attributen und Methoden:<br />

public class Cell {<br />

private int border;<br />

private boolean food;<br />

private boolean exit;<br />

}<br />

public int getBorder() {<br />

return border;<br />

}<br />

• Hinweis: Statt „Methode“ wird häufig auch der Begriff „Funktion“ verwendet.<br />

• Statt „Attribut“ werden auch häufig „Instanzvariable“ oder „Variable“ verwendet.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 69


Klassen und Objekte<br />

Attributzugriffe<br />

• Alle Attributzugriffe sollten immer über Methoden mit gleichem Namen mit vorangestelltem<br />

get bzw. set erfolgen Kapselung!<br />

Beispiel:<br />

public class Cell {<br />

private int border;<br />

private boolean food;<br />

//...<br />

public int getBorder(){<br />

return border;<br />

}<br />

public boolean isFood(){<br />

return food;<br />

}<br />

public void setBorder(int nBorder){<br />

border = nBorder;<br />

}<br />

public void setFood(boolean nFood){<br />

food = nFood;<br />

}<br />

}<br />

falls der Lese- und<br />

Schreibzugriff erlaubt<br />

sein soll Namensvergabe<br />

nach Java-Konvention<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 70


Klassen und Objekte<br />

Beispiel (Vektor, Version 1)<br />

• Aus der Mathematik bekannt: Vektoren und Matrizen.<br />

• Klasse Vector, hier eingeschränkt auf Länge 3 mit double-Zahlen (noch unvollständig und<br />

gefährlich kommt später besser):<br />

package de.hska.iwii.i2;<br />

public class Vector {<br />

private double[] values =<br />

new double[ 3 ];<br />

}<br />

public void setValue(int index,<br />

double value) {<br />

values[ index ] = value;<br />

}<br />

public double getValue(int index) {<br />

return values[ index ];<br />

}<br />

Vector<br />

- values: double[3] {bag}<br />

+ setValue(index: int, double: value)<br />

+ getValue(index: int): double<br />

package de.hska.iwii.i2;<br />

public class VectorTest {<br />

public static void main(<br />

String[] args) {<br />

Vector v1 = new Vector();<br />

v1.setValue(0, 2.0);<br />

System.out.println(v1.getValue(0));<br />

}<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 71


Klassen und Objekte<br />

Konstruktoren<br />

Definition: Konstruktor<br />

Konstruktoren dienen der gezielten Initialisierung eines Objektes bei dessen Erzeugung.<br />

• Es kann mehr als einen Konstruktor in einer Klasse geben.<br />

Beispiel (Vector, Version 2):<br />

public class Vector {<br />

private double[] values;<br />

}<br />

public Vector(int size) {<br />

values = new double[ size ];<br />

}<br />

public void setValue(int index, double value) {<br />

values[ index ] = value;<br />

}<br />

public double getValue(int index) {<br />

return values[ index ];<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 72


Klassen und Objekte<br />

Konstruktoren<br />

• Ein Konstruktor darf auch einen anderen aufrufen:<br />

public class Vector {<br />

// ...<br />

public Vector(int size) {<br />

this(size, 0.0);<br />

}<br />

}<br />

public Vector(int size, double initValue) {<br />

values = new double[ size ];<br />

for (int i = 0; i < size; ++i) {<br />

values[ i ] = initValue;<br />

}<br />

}<br />

// ...<br />

• Ohne die Angabe eines Konstruktors wird immer automatisch der Defaultkonstruktor (ohne<br />

Parameter) erzeugt (sonst nicht).<br />

• Ein Konstruktor wird immer automatisch aufgerufen, wenn ein Objekt der Klasse erzeugt<br />

wird.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 73


Klassen und Objekte<br />

Beispielmethode zur Skalarproduktberechnung<br />

• Skalarprodukt (immer noch Version 2):<br />

public class Vector {<br />

// ...<br />

public double getScalarProduct(Vector second) {<br />

double result = 0.0;<br />

for (int i = 0; i < values.length; ++i) {<br />

result += values[ i ] * second.values[ i ];<br />

}<br />

}<br />

return result;<br />

}<br />

// ...<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 74


Klassen und Objekte<br />

Variable Anzahl Übergabeparameter<br />

• Probleme:<br />

Eine Methode oder ein Konstruktor wird mit einer beliebigen Anzahl Werte desselben<br />

Typs aufgerufen.<br />

Lösungen:<br />

- Alle Werte kommen in ein Array. Das Array wird übergeben.<br />

- Java unterstützt die Übergabe einer variablen Parameteranzahl.<br />

• Beispiel Konstruktor des Vektors mit variabler Anzahl double-Werte:<br />

public class Vector {<br />

private double[] values;<br />

}<br />

public Vector(double... initValues) {<br />

values = new double[initValues.length];<br />

for (int i = 0; i < initValues.length; ++i) {<br />

values[ i ] = initValues[ i ];<br />

}<br />

}<br />

// ...<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 75


Klassen und Objekte<br />

Variable Anzahl Übergabeparameter<br />

• Aufrufe:<br />

Vector v1 = new Vector(1.0, 2.0, 3.0, 4.0); // Länge 4<br />

Vector v2 = new Vector(1.0, 2.0); // Länge 2<br />

Vector v3 = new Vector(); // Länge 0<br />

• Intern werden die Parameter in einem Array abgelegt:<br />

• Die Anzahl der Parameter kann mit array.length ermitteln werden.<br />

• Die Parameter werden mit Array-Zugriffen ausgelesen.<br />

• Das funktioniert auch für Methoden.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 76


Klassen und Objekte<br />

Aufbau und Verwendung von Klassen<br />

• Klassen kapseln Daten und arbeiten selbst auf ihren eigenen Daten:<br />

“Don't ask for the information that you need to do something;<br />

rather, ask the object that has that information to do the job for you.”<br />

• Beispiel (so nicht):<br />

public class Article {<br />

private double price;<br />

}<br />

public double getPrice() {<br />

return price;<br />

}<br />

// usw.<br />

// Implementierung einer Preiserhöhung in einer anderen Klasse<br />

public void increasePrice(Article article, double percentage) {<br />

article.setPrice(article.getPrice() * (1 + percentage / 100.0));<br />

}<br />

Problem: Lesen, Manipulation und Schreiben von Article-Daten. Die Article-Operation<br />

gehört in die Klasse!<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 77


Klassen und Objekte<br />

Aufbau und Verwendung von Klassen<br />

• Beispiel (so ist es ok):<br />

public class Article {<br />

private double price;<br />

}<br />

public double getPrice() {<br />

return price;<br />

}<br />

// usw.<br />

// Implementierung einer Preiserhöhung<br />

public void increasePrice(double percentage) {<br />

price *= (1 + percentage / 100.0));<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 78


Klassen und Objekte<br />

Statische Attribute und Methoden<br />

• Bisher: Jedes Attribut einer Klasse existiert in jedem Objekt der Klasse.<br />

• Manchmal gewünscht: Auch „globale“ Attribute, die nur einmal für eine Klasse existieren <br />

Alle Objekte einer Klasse teilen sich dieses Attribut:<br />

static Typ Attribut-Name;<br />

• Zugriff auf statische Attribute:<br />

Statische Methoden:<br />

static Typ Methode(Parameter);<br />

Aufruf einer statischen Methode einer Klasse auch ohne ein konkretes Objekt.<br />

• Statische Attribute können als globale Attribute innerhalb einer Klasse betrachtet werden.<br />

• Beispiel kommt nachher im Rahmen der Einführung von Referenzen.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 79


Klassen und Objekte<br />

final-Parameter und final-Werte<br />

• final-Parameter und final-Werte können nicht verändert werden Konstante!<br />

Beispiel:<br />

public void add(final int arg) {<br />

}<br />

// ...<br />

• final Vector vector: Unveränderliche Referenz auf ein Vektor-Objekt, dessen Inhalt<br />

aber verändert werden kann.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 80


Klassen und Objekte<br />

Primitive Datentypen und Wrapper-Klassen<br />

Für die primitiven Datentypen existieren Wrapper-Klassen<br />

Typ Größe Wertebereich Wrapper<br />

boolean true, false Boolean<br />

char 16 Bit '\u0000'‚ bis '\uFFFF' Character<br />

byte 8 Bit -2 7 bis 2 7 -1 Byte<br />

short 16 Bit -2 15 bis 2 15 -1 Short<br />

int 32 Bit -2 31 bis 2 31 -1 Integer<br />

long 64 Bit -2 64 bis 2 64 – 1 Long<br />

float 32 Bit 2 -149 bis (2-2 -23 )·2 127 Float<br />

double 64 Bit 2 -1074 bis (2-2 -52 )·2 1023 Double<br />

void<br />

Void<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 81


Klassen und Objekte<br />

Primitive Datentypen und Wrapper-Klassen<br />

Eigenschaften der Wrapper<br />

• Sie kapseln einen Wert eines primitiven Datentyps (ein Integer-Objekt nimmt genau einen<br />

int-Wert auf).<br />

• Der gekapselte Wert ist unveränderlich.<br />

• Sie besitzen Methoden zur Konvertierung vom/in den Wrapper.<br />

Wozu dienen die Wrapper?<br />

• Manche Methoden und Klassen erwarten Objekte und keine primitiven Datentypen die<br />

Wrapper kapseln die Daten dazu.<br />

• Beispiel aus dem 1. Semester: Eine ArrayList mit int-Werten kann so verwendet werden:<br />

ArrayList daten = new ArrayList(); // primitive Datentypen sind<br />

// nicht möglich<br />

daten.add(500);<br />

// wird automatisch zu<br />

// daten.add(Integer.valueOf(500));<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 82


Klassen und Objekte<br />

Primitve Datentypen und Wrapper-Klassen<br />

Automatisches Einpacken mit Wrappern (autoboxing)<br />

• Automatisches „Einpacken“ (siehe vorheriges Beispiel)<br />

ArrayList daten = new ArrayList();<br />

daten.add(66); // autoboxing<br />

daten.add(42); // autoboxing<br />

daten.add(1); // autoboxing<br />

1<br />

daten<br />

add<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 83


Klassen und Objekte<br />

Primitive Datentypen und Wrapper-Klassen<br />

• Was passiert genau?<br />

<br />

<br />

Für die ganze Zahlen -128 bis 127 existieren vordefinierte Wrapper-Objekte, die<br />

verwendet werden.<br />

Für andere Zahlenbereiche sowie float und double werden jeweils neue Objekte<br />

erzeugt Probleme beim Vergleichen:<br />

Integer boxedKlein1 = 127;<br />

Integer boxedKlein2 = 127;<br />

System.out.println(boxedKlein1 == boxedKlein2);<br />

// true<br />

Integer boxedKlein1 = 128;<br />

Integer boxedKlein2 = 128;<br />

System.out.println(boxedKlein1 == boxedKlein2);<br />

// false<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 84


Klassen und Objekte<br />

Primitive Datentypen und Wrapper-Klassen<br />

Automatisches Auspacken mit Wrappern (unboxing)<br />

• Automatisches „Auspacken“<br />

ArrayList daten = new ArrayList();<br />

daten.add(66); // autoboxing<br />

daten.add(42); // autoboxing<br />

daten.add(1); // autoboxing<br />

int wert = daten.get(0); // unboxing<br />

66<br />

daten<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 85


Klassen und Objekte<br />

Primitive Datentypen und Wrapper-Klassen<br />

• Was passiert genau?<br />

<br />

<br />

Eine null-Referenz kann nicht umgewandelt werden und führt zu einer Exception:<br />

int zahl = (Integer) null;<br />

Es lauern Fallen bei der Umwandlung von Zahlen:<br />

Integer i1 = new Integer(42);<br />

Integer i2 = new Integer(42);<br />

System.out.println(i1 >= i2);<br />

System.out.println(i1


Klassen und Objekte<br />

Innere Klassen<br />

• Klassen lassen sich ineinander schachteln.<br />

• Java unterstützt drei unterschiedliche Arten innerer Klassen:<br />

<br />

<br />

<br />

nicht-statische innere Klassen<br />

statische innere Klassen<br />

anonyme innere Klassen<br />

• Einsatzgebiete:<br />

<br />

<br />

Die inneren Klassen werden hauptsächlich in der äußeren benötigt oder von dieser<br />

erzeugt.<br />

Beispiel (kommt später): Iteratoren<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 87


Klassen und Objekte<br />

Innere Klassen: Nicht-statische innere Klassen<br />

• Einsatz: Das Erzeugen eines Objektes der inneren Klasse erfolgt immer innerhalb der Grenzen<br />

der äußeren Klasse (z.B. in einer der Methoden oder im Konstruktor).<br />

• Beispiel:<br />

public class Outer {<br />

class Inner {<br />

private int attr1;<br />

public void method1(){}<br />

public void method2(){<br />

method1();<br />

Outer.this.method1();<br />

}<br />

}<br />

public void method1(){}<br />

}<br />

• Innere Klassen dürfen weder statische Methoden noch statische Attribute besitzen.<br />

• Outer darf auf alle Methoden und Attribute von Inner zugreifen.<br />

• Inner darf auf alle Methoden und Attribute von Outer zugreifen.<br />

• Innere und äußere Klasse sind somit fest miteinander verbunden.<br />

• Erzeugte Dateien: Outer.class, Outer$Inner.class<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 88


Klassen und Objekte<br />

Innere Klassen: Statische innere Klassen<br />

• Einsatz: Das Erzeugen eines Objektes der inneren Klasse kann außerhalb der Grenzen der<br />

äußeren Klasse erfolgen.<br />

• Beispiel:<br />

public class Outer {<br />

static class Inner {<br />

private int attr1;<br />

public void method1(){}<br />

public void method2(){<br />

method1();<br />

}<br />

}<br />

private int attr2;<br />

public void method1(){}<br />

}<br />

• Die innere Klasse ist nicht an die äußere gekoppelt und kann daher nicht auf Attribute und<br />

Methoden der äußeren Klasse zugreifen.<br />

• Erzeugte Dateien: Outer.class, Outer$Inner.class<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 89


Klassen und Objekte<br />

Innere Klassen: Anonyme innere Klassen<br />

• Einsatz: Mit dem Erzeugen einer Klasse wird auch gleichzeitig ein Objekt angelegt. Die Klasse<br />

wird nur einmalig benötigt.<br />

• Häufig im Zusammenhang mit dem Implementieren von Schnittstellen verwendet:<br />

• Beispiel:<br />

public class Outer {<br />

public void method() {<br />

Runnable runObject = new Runnable() {<br />

@Override<br />

public void run() {<br />

System.out.println("Huhu");<br />

}<br />

};<br />

runObject.run();<br />

}<br />

}<br />

• Runnable ist eine Schnittstelle kommt noch genauer<br />

• Die anonyme Klasse darf nur auf finale lokale Variablen der Methode zugreifen.<br />

• Die anonyme Klasse darf auf Attribute und Methoden der äußeren Klassen zugreifen.<br />

• Erzeugte Dateien: Outer.class, Outer$1.class<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 90


Fehlererkennung<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 91


Fehlererkennung<br />

Fehlerhafte Methodenaufrufe<br />

• Idee: Die eigenen Methoden und Klassen werden eventuell falsch oder mit falschen Daten<br />

aufrufen.<br />

• Auch wenn der eigene Algorithmus korrekt ist, darf er nicht durch falsche Werte<br />

durcheinander geraten.<br />

• Denn: Programme werden im Laufe der Zeit permanent verändert. Fehler können daher<br />

immer wieder einmal auftreten.<br />

• Konsequenz: Ein Profi sichert seine eigenen Klassen und Methoden gegen eine fehlerhafte<br />

Verwendung ab.<br />

• In Kombination mit einem sauberen Software-Entwurf und anschließenden Tests, stellt die<br />

defensive Programmierung einen wichtigen Schritt in Richtung stabiler Programme dar.<br />

• Der Anwender sollte Programmfehler nie zu Gesicht bekommen.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 92


Fehlererkennung<br />

Fehlerhafte Methodenaufrufe<br />

• 3 Strategien zur Parameterbehandlung:<br />

<br />

<br />

<br />

Müll rein – nichts raus<br />

Müll rein – Fehlernachricht raus<br />

Müll rein – Müll raus (nicht akzeptabel!)<br />

• Daher: Prüfen aller Eingabeparameter<br />

<br />

<br />

<br />

Numerische Werte innerhalb vorgegebener Toleranzen<br />

Maximale Länge von Strings<br />

Randbedingungen wie 0, "", null usw.<br />

• Festlegen und dokumentieren, wie fehlerhafte Parameter behandelt werden sollen:<br />

<br />

<br />

<br />

<br />

Rückgabe eines Fehlercodes (false, -1, ...). Besser: Ausnahmen<br />

Aufruf einer Fehlerbehandlungsroutine<br />

Eintrag in einer Protokolldatei erstellen<br />

Programm beenden<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 93


Fehlererkennung<br />

Fehlerhafte Methodenaufrufe<br />

• Kontrakt zwischen einer Klasse und den Nutzern einer Klasse:<br />

Beschreibt, welche Voraussetzungen (Vorbedingungen) ein Aufrufer der Operation<br />

schaffen muss, damit die Operation durchgeführt werden kann.<br />

Legt fest, welche Leistung (Nachbedingungen) die Operation erbringt, sofern die<br />

Vorbedingungen eingehalten sind.<br />

• Vorbedingungen (engl. Preconditions)<br />

Der Aufrufer der Operation ist verpflichtet, diese Bedingungen beim Aufruf der<br />

Operation herzustellen.<br />

Sind die Vorbedingungen nicht erfüllt, ist die Operation nicht verpflichtet, ihre<br />

spezifizierte Aufgabe zu erfüllen.<br />

Vorbedingungen sind damit der Kontraktbestandteil, den der Aufrufer einer Operation<br />

einzuhalten hat.<br />

Sind die Vorbedingungen eingehalten, ist der Aufgerufene wiederum verpflichtet, die<br />

Nachbedingungen herzustellen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 94


Fehlererkennung<br />

Fehlerhafte Methodenaufrufe<br />

• Nachbedingungen (engl. Postconditions)<br />

Eine Klasse, die eine Operation implementiert, sichert zu, dass die Nachbedingungen<br />

unmittelbar nach Aufruf der Operation gelten.<br />

Die Zusicherung gilt nur, wenn der Aufrufer die für die Operation definierten<br />

Vorbedingungen eingehalten hat.<br />

Zusätzlich können auch nach außen zugesicherte Bedingungen vereinbart sein, die<br />

immer gelten sollen, unabhängig vom Aufruf einer Operation.<br />

• Invarianten (engl. Invariants)<br />

Invarianten sind Eigenschaften und Beziehungen zwischen Attributen eines Objekts, die<br />

sich durch keine Operation ändern lassen.<br />

Invarianten, die für eine Klasse definiert werden, gelten für alle Objekte der Klasse.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 95


Fehlererkennung<br />

Fehlerhafte Methodenaufrufe<br />

• Deklaration von Bedingungen in UML<br />

<br />

<br />

Ziel: möglichst automatische Überprüfbarkeit im späteren Quelltext<br />

Einführung der Object Constraint Language (OCL)<br />

• Object Constraint Language (OCL)<br />

<br />

<br />

<br />

<br />

<br />

Die OCL wird verwendet, um zusätzliche Bedingungen darzustellen, die sich mit den<br />

sonstigen Beschreibungsmitteln der UML nicht oder nur umständlich ausdrücken lassen.<br />

OCL stellt dabei eine rein deklarative Beschreibungsmöglichkeit zur Verfügung, um<br />

sogenannte Constraints auszudrücken.<br />

Ein Constraint ist ein Ausdruck, der entweder wahr oder falsch ist.<br />

OCL eignet sich sehr gut, um Vorbedingungen, Nachbedingungen und Invarianten von<br />

Operationen auszudrücken.<br />

Hier: keine vollständige Einführung in OCL<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 96


Fehlererkennung<br />

Fehlerhafte Methodenaufrufe<br />

• Beispiel zu OCL:<br />

Account<br />

- number: int<br />

- balance: int<br />

+ payOff(amount: int)<br />

context<br />

Account::payOff<br />

pre: balance >= amount<br />

post: balance = balance - amount<br />

• Wozu Constraints? Im Quelltext sind sie doch sowieso nicht sichtbar. Falsch:<br />

<br />

<br />

Mit Assertions (Zusicherungen) lassen sich Vorbedingungen manuell überprüfen.<br />

Einhaltung der Vorbedingungen können mit http://sourceforge.net/projects/ocl4java/<br />

automatisch überwacht werden.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 97


Zusicherungen<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 98


Zusicherungen<br />

Fehlerhafte Methodenaufrufe<br />

• Idee: Jede Funktion oder Methode schützt sich selbst gegen beispielsweise falsche<br />

Aufrufparameter oder falsche Zustände.<br />

• Realisierung:<br />

Die Anweisung assert wird zur Prüfung der Vor- und Nachbedingungen einer Methode<br />

verwendet.<br />

Sie wertet eine übergebene Bedingung aus. Ist diese falsch, so wird das Programm mit<br />

einem AssertionError beendet.<br />

• Beispiel Methode sqrt:<br />

public double sqrt(double value) {<br />

assert value >= 0.0;<br />

// Nicht negativ<br />

// Wurzelberechnung<br />

}<br />

• Aufruf mit:<br />

x.sqrt(42.0); // OK<br />

x.sqrt(-66.66); // Abbruch<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 99


Zusicherungen<br />

Fehlerhafte Methodenaufrufe<br />

• Verwendungen:<br />

<br />

<br />

<br />

<br />

assert Bedingung;<br />

- Der Ausdruck muss einen Boole‘schen Wert ergeben.<br />

- Ist der Wert false, so wird dieses als Fehler betrachtet.<br />

- Ist der Wert true, so wird das Programm normal fortgesetzt.<br />

assert value >= 0.0;<br />

assert Bedingung : Meldungstext;<br />

- Es gelten die Aussagen wie im ersten Fall.<br />

- Zusätzlich wird hier ein Text übergeben, der in die Ausnahme aufgenommen wird.<br />

assert value >= 0.0 : "Die Wurzel aus 0 ist undefiniert."<br />

Assertions müssen aktiviert werden:<br />

- Alle aktivieren: java -ea Main.class<br />

- Nur im Paket de.hska und dessen Unterpaketen: java -ea:de.hska...<br />

Sind Assertions nicht aktiv, dann werden sie ignoriert.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 100


Zusicherungen<br />

Fehlerhafte Methodenaufrufe: Ticketautomat<br />

• Programmierung eines<br />

sehr einfachen Ticketautomaten:<br />

<br />

Der Preis erscheint auf<br />

dem Display (Einheitspreis in Cent).<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 101


Zusicherungen<br />

Fehlerhafte Methodenaufrufe: Ticketautomat<br />

<br />

Der Kunde zahlt solange mit Münzen oder Scheinen, bis der Betrag erreicht ist (muss<br />

passend bezahlen).<br />

<br />

<br />

Nach dem Geldeinwurf wird der Restbetrag angezeigt.<br />

Nach Erreichen des Betrags wird der Fahrschein ausgegeben.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 102


Zusicherungen<br />

Fehlerhafte Methodenaufrufe: Ticketautomat<br />

• Benötigte Attribute:<br />

<br />

<br />

int ticketPrice: Preis für ein Ticket<br />

int paidPrice: bereits bezahlter Preis<br />

• Benötigte Methoden, 1. Versuch:<br />

<br />

<br />

<br />

<br />

<br />

Konstruktor: Einheitspreis als int-Parameter flexibel<br />

void requestTicket(): Ticket anfordern<br />

int requestPrice(): (Rest-)Preis für das Ticket abfragen<br />

void insertMoney(int amount): Geld einwerfen<br />

void printTicket(): Ticket ausdrucken<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 103


Zusicherungen<br />

Fehlerhafte Methodenaufrufe: Ticketautomat<br />

• Klasse in UML:<br />

TicketMachine<br />

-ticketPrice: int<br />

-paidPrice: int<br />

+TicketMachine(price: int)<br />

+requestTicket()<br />

+requestPrice(): int<br />

+insertMoney(amount: int)<br />

+printTicket()<br />

context TicketMachine::printTicket<br />

pre: paidPrice >= ticketPrice<br />

post: paidPrice = 0<br />

context TicketMachine::requestTicket<br />

post: paidPrice = 0<br />

context TicketMachine::insertMoney<br />

pre: amount > 0<br />

post: paidPrice = paidPrice + amount<br />

context TicketMachine::TicketMachine<br />

pre: price > 0<br />

post: (ticketPrice = price and<br />

paidPrice = 0)<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 104


Zusicherungen<br />

Fehlerhafte Methodenaufrufe: Ticketautomat<br />

• Quelltext:<br />

public class TicketMachine {<br />

// Die Attribute der Klasse<br />

private int ticketPrice;<br />

private int paidPrice;<br />

// Konstruktor zum Initialisieren<br />

public TicketMachine(int price) {<br />

ticketPrice = price;<br />

paidPrice = 0;<br />

}<br />

// Ticket anfordern --> löscht den bisher bezahlten Betrag<br />

public void requestTicket() {<br />

paidPrice = 0;<br />

}<br />

// (Noch) zu zahlenden Betrag anfordern.<br />

public int requestPrice() {<br />

return ticketPrice – paidPrice;<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 105


Zusicherungen<br />

Fehlerhafte Methodenaufrufe: Ticketautomat<br />

}<br />

// Geld einwerfen --> Restbetrag reduzieren.<br />

public void insertMoney(int amount) {<br />

paidPrice += amount;<br />

}<br />

// Ticket "ausdrucken"<br />

public void printTicket() {<br />

System.out.println("Ticket xyz");<br />

System.out.println("Preis: " + ticketPrice);<br />

paidPrice = 0;<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 106


Zusicherungen<br />

Fehlerhafte Methodenaufrufe: Ticketautomat<br />

• Eine perfekte Lösung Nein!!!<br />

• Probleme:<br />

<br />

<br />

Keine Prüfungen der Methodenparameter und internen Zustände:<br />

- negative Beträge eingeworfen<br />

- Ticket drucken, obwohl Endbetrag nicht erreicht wurde<br />

- Was passiert, wenn zu viel Geld eingeworfen wurde?<br />

- Der Ticketpreis im Konstruktor ist ungeprüft.<br />

Einhaltung der Constraints wurde nicht geprüft!!!<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 107


Zusicherungen<br />

Fehlerhafte Methodenaufrufe: Ticketautomat<br />

• Quelltext mit Prüfungen:<br />

public class TicketMachine {<br />

// Die Attribute der Klasse<br />

private int ticketPrice;<br />

private int paidPrice;<br />

// Konstruktor zum Initialisieren<br />

public TicketMachine(int price) {<br />

assert price > 0;<br />

ticketPrice = price;<br />

paidPrice = 0;<br />

}<br />

context TicketMachine::TicketPrice<br />

pre: price > 0<br />

post: (ticketPrice = price and<br />

paidPrice = 0)<br />

// Ticket anfordern --> löscht den bisher bezahlten Betrag<br />

public void requestTicket() {<br />

paidPrice = 0;<br />

}<br />

context TicketMachine::requestTicket<br />

post: paidPrice = 0<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 108


Zusicherungen<br />

Fehlerhafte Methodenaufrufe: Ticketautomat<br />

// (Noch) zu zahlenden Betrag anfordern.<br />

public int requestPrice() {<br />

return ticketPrice – paidPrice;<br />

}<br />

context TicketMachine::insertMoney<br />

pre: amount > 0<br />

post: paidPrice = min(paidPrice + amount,<br />

ticketPrice)<br />

// Geld einwerfen --> Restbetrag reduzieren.<br />

// Zuviel bezahlten Betrag wieder auswerfen.<br />

public int insertMoney(int amount) {<br />

assert amount > 0;<br />

int diff = ticketPrice – paidPrice - amount;<br />

paidPrice += amount;<br />

if (paidPrice > ticketPrice)<br />

paidPrice = ticketPrice;<br />

return diff >= 0 ? 0 : -diff;<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 109


Zusicherungen<br />

Fehlerhafte Methodenaufrufe: Ticketautomat<br />

}<br />

// Ticket "ausdrucken"<br />

public void printTicket() {<br />

assert paidPrice >= ticketPrice;<br />

System.out.println("Ticket xyz");<br />

System.out.println("Preis: " + ticketPrice);<br />

paidPrice = 0;<br />

}<br />

context TicketMachine::printTicket<br />

pre: paidPrice >= ticketPrice<br />

post: paidPrice = 0<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 110


Klassen und Objekte<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 111


Klassen und Objekte<br />

Beispiel: Ringpuffer<br />

• Eine erste einfache Implementierung eines Ringpuffers:<br />

<br />

<br />

Ein Ringpuffer kann als ein Array mit speziellen Lese- und Schreiboperationen<br />

interpretiert werden:<br />

Das Array dieses Ringpuffers kann nur int-Daten aufnehmen.<br />

Ein Leseindex RI zeigt die Position an, an der der nächste Wert gelesen wird. Nach dem<br />

Lesen wird der Index automatisch erhöht. Am Ende des Arrays wird der Index auf 0<br />

gesetzt. Somit handelt es sich um ein zerstörendes Lesen, bei dem der Wert nach dem<br />

Lesen nicht mehr im Ringpuffer zugreifbar ist.<br />

Ein Schreibindex WI zeigt die Position an, an die der nächste Wert geschrieben wird.<br />

Nach dem Schreiben wird der Index automatisch erhöht. Am Ende des Arrays wird der<br />

Index auf 0 gesetzt.<br />

Der Ringpuffer ist leer, wenn WI genauso groß wie RI ist.<br />

Der Ringpuffer ist voll, wenn gilt: WI hätte nach dem Erhöhen den Wert von RI.<br />

• Bessere Variante: siehe Übungsaufgabe<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 112


Klassen und Objekte<br />

Referenzen und dynamische Speicherverwaltung<br />

• Warum kann man Objekte und Variable nicht einfach alle auf dem Stack verwalten?<br />

• Wie werden Objekte auf dem Heap erzeugt und wieder freigegeben?<br />

• Referenzen sind spezielle Variable, die auf Objekte verweisen.<br />

• Zum Bau komplexer Datenstrukturen sind der Heap und Referenzen zwingend<br />

notwendig.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 113


Klassen und Objekte<br />

Referenzen und dynamische Speicherverwaltung<br />

Definition: Referenz<br />

Eine Referenz hat einen unveränderlichen Typ T. Sie enthält einen Verweis auf genau ein<br />

oder gar kein Objekt der Klasse T. Das Objekt liegt auf dem Heap.<br />

• Beispiel für eine Referenz, die auf kein Objekt verweist:<br />

Bruch brReferenz = null;<br />

• Beispiel für eine Referenz auf ein Bruch-Objekt:<br />

Bruch brReferenz = new Bruch(2,3);<br />

• Intern enthält die Referenz die Speicheradresse des Objektes.<br />

• Es existieren zwei Referenzen mit einer besonderen Semantik:<br />

<br />

null: Die Referenz verweist auf gar kein Objekt.<br />

this: Die Referenz verweist auf die eigene Objektinstanz (kann nur in Konstruktoren<br />

oder nicht-statischen Methoden verwendet werden).<br />

• Es gibt auch sogenannte schwache Referenzen, die hier aber nicht betrachtet werden sollen.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 114


Klassen und Objekte<br />

Referenzen und dynamische Speicherverwaltung<br />

Definition: Heap<br />

Speicherbereich, in dem der Entwickler selbst die Lebensdauer seiner Daten kontrolliert. Mit<br />

new wird ein Bereich reserviert. Die Freigabe erfolgt automatisch durch den Garbage-<br />

Collector.<br />

• Der Operator new führt die folgenden Schritte durch:<br />

<br />

<br />

<br />

Reservierung des benötigten Speichers auf dem Heap<br />

Aufruf eines Konstruktors<br />

Rückgabe einer Referenz auf das erzeugte Objekt<br />

• Anforderung eines Speicherbereichs mit Aufruf des Defaultkonstruktors:<br />

Syntax:<br />

Beispiel:<br />

Klasse ref = new Klasse();<br />

Pacman pacmanRef = new Pacman();<br />

• Anforderung eines Speicherbereichs mit Aufruf eines beliebigen Konstruktors:<br />

Syntax:<br />

Klasse ref = new Klasse(init);<br />

Beispiel:<br />

Pacman pacmanRef = new Pacman(x, y);<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 115


Klassen und Objekte<br />

Referenzen und dynamische Speicherverwaltung – new-Operator<br />

• Der Operator new führt die folgenden Schritte bei Arrays durch:<br />

<br />

<br />

<br />

Reservierung des benötigten Speichers auf dem Heap<br />

Initialisierung des Arrays:<br />

- bei Arrays mit primitiven Datentypen: 0, 0.0 oder false<br />

- bei Arrays mit Referenzen: null<br />

Rückgabe einer Referenz auf das Array<br />

• Anforderung eines Speicherbereichs der Größe des Arrays mit primitiven Daten:<br />

Syntax:<br />

Beispiel:<br />

Typ[] ref = new Typ[ size ]; int[] iRef = new int[ 10 ];<br />

• Das Array enthält 10 int-Daten mit dem Wert 0.<br />

• Anforderung eines Speicherbereichs der Größe des Arrays mit Referenzen:<br />

Syntax:<br />

Beispiel:<br />

Typ[] ref = new Typ[ size ]; Bruch[] brRef = new Bruch[ 10 ];<br />

Das Array enthält 10 null-Referenzen. Es werden keine Bruch-Objekte angelegt!<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 116


Klassen und Objekte<br />

Referenzen und dynamische Speicherverwaltung – new-Operator für Arrays<br />

• Ausführlicheres Beispiel: 4 Referenzen auf Ghost-Objekte in einem Array:<br />

Ghost[] allGhosts = new Ghost[ 4 ]; // Platz für vier Geister<br />

for (int i = 0; i < allGhosts.length; i++)<br />

allGhosts[ i ] = new Ghost(3, 1);<br />

for (int i = 0; i < allGhosts.length; i++)<br />

allGhosts[ i ].setX(12);<br />

0x1240<br />

0x1240 0x2000 0x2010 0x2020<br />

allGhosts<br />

0x2030<br />

Fiktive Adressen!<br />

Geist 1 Geist 2 Geist 3<br />

0x2000 0x2010 0x2020<br />

Geist 4<br />

0x2030<br />

• Mehrdimensionale Arrays lassen genauso erzeugen.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 117


Klassen und Objekte<br />

Referenzen und dynamische Speicherverwaltung – Speicherfreigabe<br />

Was passiert mit Objekten, auf die keine Referenzen mehr existieren?<br />

• Sie sind durch das eigene Programm nicht mehr erreichbar.<br />

• Der interne Garbage-Collector kann sie beseitigen und wieder dem Freispeicher zuordnen.<br />

• Vor der Speicherfreigabe wird die Methode protected void finalize() des zu<br />

löschenden Objektes aufgerufen.<br />

• Es kann passieren, dass die Objekte auf dem Heap bleiben, wenn genügend Speicher<br />

vorhanden ist Zeitpunkt der Freigabe ist nicht vorhersehbar.<br />

• Manueller Aufruf des Garbage-Collectors: Runtime.getRuntime().gc();<br />

Es werden trotzdem nicht alle unerreichbaren Objekte freigegeben.<br />

Mehrfacher Aufruf, bis sich der freie Speicher nicht mehr ändert:<br />

long freeMem = Runtime.getRuntime().freeMemory();<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 118


Klassen und Objekte<br />

Referenzen und dynamische Speicherverwaltung – Singleton<br />

Definition: Singleton<br />

Eine Klasse, von der nur ein Objekt erzeugt werden kann.<br />

• Beispielimplementierung (nicht perfekt).<br />

public class Logger {<br />

private static Logger instance;<br />

// Privater Konstruktor<br />

private Logger(){<br />

}<br />

public static Logger getInstance(){<br />

if (instance == null)<br />

instance = new Logger();<br />

return instance;<br />

}<br />

public void test() {<br />

Logger log1 = new Logger(); // Fehler<br />

Logger log2 = Logger.getInstance();<br />

Logger log3 = Logger.getInstance();<br />

}<br />

log2.log("Wichtige Nachricht");<br />

// Oder kürzer<br />

Logger.getInstance().log("Nachricht");<br />

}<br />

public void log(String message) {<br />

// Ausgabe<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 119


Klassen und Objekte<br />

Referenzen und dynamische Speicherverwaltung – Beispiel<br />

• Implementierung einer einfach verketteten Liste doppelte Verkettung ist eine<br />

Übungsaufgabe!<br />

• Welche Klassen werden benötigt?<br />

• Implementierung einiger Methoden der Klassen<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 120


Überladen von Methoden<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Typinformationen<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassendiagramme<br />

Ein-,<br />

Ausgabe<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Annotationen<br />

Überladen<br />

Laufzeittypinfo.<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 121


Überladen von Methoden<br />

Definition: Überladen von Methoden<br />

Eine Klasse besitzt zwei oder mehr Methoden mit demselben Namen und unterschiedlichen<br />

Parametertypen.<br />

Die passende Methode wird durch den Compiler ermittelt, indem er auch<br />

Typkonvertierungen durchführt.<br />

Der Rückgabetyp darf unterschiedlich sein.<br />

Beispiel:<br />

Klassenname<br />

-attribut: int<br />

+methode()<br />

+methode(wert: int)<br />

+methode(wert: string)<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 122


Überladen von Methoden<br />

• Einsatz: Verwendung der gleichen Methode mit unterschiedlichen Parametertypen.<br />

• Vorteil: Keine explizite Konvertierung der Argumente im Aufruf.<br />

• Beispiel: Vereinfachter Auszug aus der bereits eingeführten Klasse GameController, die in<br />

Pacman die Figuren steuert.<br />

GameController<br />

+collisionOfPacmanWith(ghost: Ghost)<br />

+collisionOfPacmanWith(cherry: Cherry)<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 123


Überladen von Methoden<br />

Auswahl der passenden Methode<br />

Auswahlkriterien durch den Compiler:<br />

• Die Anzahl der Parameter muss zum Aufruf passen.<br />

• Alle Übergabeparameter müssen in die Parametertypen der Methode konvertierbar sein.<br />

Beispiel:<br />

public class PrintStream {<br />

public void println(long x){}<br />

public void println(char x){}<br />

}<br />

Aufruf:<br />

PrintStream out = ...<br />

out.println(123);<br />

PrintStream<br />

+println(x: long)<br />

+println(x: char)<br />

int wird zu long<br />

• Für alle Übergabeparameter wird der kleinste passende Typ gesucht.<br />

Beispiel: char int, vor char long.<br />

• Ein größerer Typ wird nie in einen kleineren Typ umgewandelt.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 124


Überladen von Methoden<br />

• Es wird die Methode mit der kleinsten Summe der „Konvertierungsabstände“ aller Parameter<br />

ermittelt.<br />

• Existieren mehrere Methoden mit gleichem minimalen Abstand, so wird ein<br />

Übersetzungsfehler gemeldet.<br />

• Beispiel (OK, ziemlich sinnlos):<br />

public class MyClass {<br />

public void method(long x, int y);<br />

public void method(int x, long y);<br />

}<br />

Aufruf:<br />

MyClass cl = new MyClass();<br />

cl.method(123, 456 ); Fehler !<br />

cl.method(123L,456 );<br />

cl.method(123, 456L);<br />

MyClass<br />

+method(x: long, y: int)<br />

+method(x: int, y: long)<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 125


Vererbung<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 126


Vererbung<br />

Motivation<br />

• Wie können existierende Klassen wiederverwendet werden?<br />

• Welche Methoden sollte eine Klasse immer unterstützen?<br />

• Welche Arten von Beziehungen können zwischen Objekten bestehen?<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 127


Vererbung<br />

Motivation<br />

• Eigenschaften, die für eine Figur gelten, gelten eventuell auch für spezielle Figuren:<br />

Figure<br />

Ghost<br />

Pacman<br />

• Vererbungsbeziehungen können mit der Vererbungshierarchie in der Biologie verglichen<br />

werden:<br />

Animal<br />

Mammal<br />

Reptile<br />

Kangaroo<br />

Koala<br />

Crocodile<br />

• Ein Koalabär ist ein Säugetier (Mammal) ist ein Tier.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 128


Vererbung<br />

Begriffe<br />

• Es gibt zwei Arten der Vererbung in Programmiersprachen:<br />

<br />

Vererbung der Spezifikation: wichtiges Konzept der objektorientierten Programmierung<br />

Vererbung der Implementierung: Mittel zur Vermeidung von Redundanzen mit einigen<br />

konzeptuellen und praktischen Problemen<br />

• Beide Techniken werden häufig unter dem Begriff der Vererbung zusammengefasst.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 129


Vererbung<br />

Begriffe<br />

Definition: Vererbung<br />

Vererbung ist eine Programmiersprachenkonzept zur Umsetzung einer Relation zwischen<br />

einer Ober- und einer Unterklasse:<br />

Eine Klasse AbgelKlasse ist dann eine Unterklasse der Klasse BasisKlasse, wenn<br />

AbgelKlasse die Spezifikation von BasisKlasse erfüllt, umgekehrt aber BasisKlasse<br />

nicht die Spezifikation von AbgelKlasse. Die Klasse BasisKlasse ist dann eine Oberklasse<br />

von AbgelKlasse.<br />

BasisKlasse<br />

+operation1()<br />

AbgelKlasse hält Vorund<br />

Nachbedingung von<br />

operation1 der<br />

BasisKlasse ein.<br />

AbgelKlasse<br />

+operation1()<br />

+operation2()<br />

AbgelKlasse erweitert<br />

die eigene Spezifikation<br />

um operation2.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 130


Vererbung<br />

Begriffe<br />

• Die Oberklasse vererbt ihre Spezifikation (Vor- und Nachbedingungen) an die Unterklasse.<br />

• Durch Unterklassen wird das Verhalten der Oberklasse nicht verändert.<br />

• Durch Vererbung (Ableitung) entsteht eine Klassenhierarchie.<br />

-x: int<br />

-y: int<br />

Figure<br />

+setX(x: int)<br />

+setY(y: int)<br />

Oberklasse<br />

Superklasse<br />

Basisklasse<br />

Generalisierung<br />

ist Spezialfall von<br />

ist Erweiterung von<br />

ist Verallgemeinerung<br />

von<br />

-IQ: int<br />

Ghost<br />

+getIQ(): int<br />

Pacman<br />

-mouthOpening: boolean<br />

+isMouthOpening(): boolean<br />

Unterklasse<br />

Subklasse<br />

abgeleitete Klasse<br />

Spezialisierung<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 131


Vererbung<br />

Begriffe<br />

Generalisierung und Spezialisierung – Begriffe<br />

• Prozess der Klassenbildung ist ein Abstraktionsvorgang:<br />

Spezialisierung: Aus bestehenden Klassen können spezialisierte Unterklassen<br />

(abgeleitete Klassen) gebildet werden.<br />

Generalisierung: Gemeinsamkeiten bestehender Klassen können in gemeinsame<br />

Oberklassen (Basisklasse) verlagert werden.<br />

Ergebnis: Klassenhierarchien aus Ober- und Unterklassen.<br />

• Oberklassen: Allgemeiner und abstrakter als Unterklassen.<br />

• Unterklassen: Spezieller und konkreter als Oberklassen.<br />

• Der Sprachmechanismus, der dieses Konzept unterstützt, wird Vererbung genannt.<br />

• Wichtig: Eine Unterklasse ist ein Untertyp von Oberklasse. Damit kann die Unterklasse<br />

überall dort verwendet werden, wo die Oberklasse erwartet wird.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 132


Vererbung<br />

Begriffe<br />

• Eine Unterklasse ist ein Stellvertreter für die Oberklasse.<br />

• Sie kann Methoden der Oberklasse überschreiben (umdefinieren).<br />

Klassen<br />

Objekte<br />

-x: int<br />

-y: int<br />

Figure<br />

+setX(x: int)<br />

+setY(y: int)<br />

Speicher<br />

x = 1<br />

y = 4<br />

IQ = 70<br />

ghost1<br />

pacman<br />

-IQ: int<br />

Ghost<br />

+getIQ(): int<br />

Pacman<br />

-mouthOpening: boolean<br />

+isMouthOpening(): boolean<br />

x = 2<br />

y = 13<br />

mouthOpening = false<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 133


Vererbung<br />

Vererbung der Spezifikation<br />

Allgemeiner Fall: Vererbung der Spezifikation<br />

• Eine Unterklasse erbt grundsätzlich die Spezifikation ihrer Oberklasse.<br />

• Die Unterklasse übernimmt damit alle Verpflichtungen und Zusicherungen der Oberklasse.<br />

• Häufiger wird auch der Begriff Vererbung von Schnittstellen benutzt.<br />

• Vererbung der Spezifikation: Eine Unterklasse übernimmt die Verpflichtungen (Vor- und<br />

Nachbedingungen), die sich aus der Spezifikation der Oberklasse ergeben.<br />

• Vererbung ist mehr als die einfache Syntax zur Implementierung einer Schnittstelle.<br />

• Prinzip der Ersetzbarkeit: Wenn die Klasse B eine abgeleitete Klasse der Klasse A ist, dann<br />

können in einem Programm alle Objekte der Klasse A durch Objekte der Klasse B ersetzt<br />

worden sein, und es gelten trotzdem weiterhin alle zugesicherten Eigenschaften der Klasse A.<br />

• Java unterstützt dieses Konzept durch eigene Sprachmittel, C++ nicht kommt gleich<br />

genauer.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 134


Vererbung<br />

Vererbung der Implementierung<br />

Spezieller Fall: Vererbung der Implementierung<br />

• Anwendungsbeispiel: Es gibt eine Basisklasse, die nicht vollständig durch spezialisierte<br />

abgeleitete Klassen abgedeckt wird.<br />

• Es gibt also Objekte der Basisklasse.<br />

• Beispiel (in der Basisklasse sind z.B. Beamte und Rentner):<br />

Steuerzahler<br />

Angestellter<br />

Selbstaendiger<br />

• Syntaxbeispiel:<br />

public class Angestellter extends Steuerzahler {<br />

}<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 135


Vererbung<br />

Vererbung der Implementierung<br />

Beispiel: Erben gesetzlicher Regelungen (aus „Praxisbuch Objektorientierung“)<br />

• Gesetzliche Regelungen werden auf verschiedenen Ebenen vorgenommen. Für eine in<br />

Karlsruhe lebende Person gilt:<br />

Die europäische Union legt rechtliche Rahmenbedingungen fest.<br />

Die Bundesrepublik Deutschland hat gesetzliche Regelungen für das Steuerrecht.<br />

Das Land Baden-Württemberg hat wiederum eigene spezielle Regelungen.<br />

Schließlich legt die Stadt Karlsruhe noch eigene Regelungen fest, zum Beispiel den so<br />

genannten Hebesatz für die Gewerbesteuer.<br />

• „Vererbung der Regelungen“<br />

Die Karlsruher-Regelung erbt von der des Landes Baden-Württemberg.<br />

Diese wiederum erben die Regeln des Bundes.<br />

Der Bund muss die Regeln der EU akzeptieren.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 136


Vererbung<br />

Vererbung der Implementierung<br />

• Effekte der Vererbung der Umsetzung:<br />

Beispiel: Der allgemeine Einkommenssteuersatz wird für Karlsruhe direkt aus der<br />

Regelung des Bundes übernommen.<br />

Eine Änderung des Einkommensteuersatzes bundesweit führt auch zu einer Änderung in<br />

Karlsruhe.<br />

In einem bestimmten Rahmen können eigene Umsetzungen in den speziellen Fällen<br />

erfolgen. Beispiel: Jede Kommune hat eigene Gewerbesteuerumsetzung.<br />

• Die Regelungen sind hierarchisch organisiert, wobei die weiter oben liegenden Regeln jeweils<br />

weiter unten liegende überschreiben.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 137


Vererbung<br />

Vererbung der Implementierung<br />

• Suche einer passenden Regelung anhand des Beispiels:<br />

Suchrichtung<br />

Steuerrecht Karlsruhe<br />

Steuerrecht BW<br />

Steuerrecht Bund<br />

Steuerrecht EU<br />

<br />

<br />

Suche eines Gesetzes durch Suchen in den Büchern „von oben nach unten“ im Stapel.<br />

Vorteil:<br />

- Karlsruhe muss nicht den kompletten Gesetzestext der EU beinhalten.<br />

- Eine Änderung innerhalb der EU wird automatisch übernommen.<br />

- Nur kleinere Anpassungen werden lokal festgelegt Karlsruher Recht muss mit EU-<br />

Recht übereinstimmen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 138


Vererbung<br />

Vererbung der Implementierung<br />

• Klassenhierarchie der Regelungen:<br />

Steuerrecht-<br />

EU<br />

Steuerrecht-<br />

Bund<br />

Steuerrecht-<br />

BW<br />

Steuerrecht-<br />

Karlsruhe<br />

• Wie wird eine Klassenhierarchie implementiert?<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 139


Vererbung<br />

Vererbung der Implementierung – Syntax<br />

• Beispiel:<br />

<br />

<br />

Figure als allgemeine Basisklasse für eine Figur<br />

Ghost als spezielle Figur<br />

public class Figure {<br />

private int xPos;<br />

private int yPos;<br />

}<br />

public Figure(int xPos, int yPos) { /* ... */ }<br />

public void move(int xPos, int yPos) { /* ... */ }<br />

//...<br />

public class Ghost extends Figure {<br />

private boolean dangerous;<br />

}<br />

public Ghost(int xPos, int yPos, boolean dangerous) { /* ... */ }<br />

public boolean isDangerous() { /* ... */ }<br />

public void move(int xPos, int yPos) { /* ... */ }<br />

//...<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 140


Vererbung<br />

Vererbung der Implementierung – Konstruktorenreihenfolge<br />

• Frage: Wie funktioniert der Konstruktoraufruf in Figure jetzt, wenn ein Ghost-Objekt<br />

erzeugt wird?<br />

• Antwort: Der Konstruktor von Ghost kann Argumente an den Konstruktor der Basisklasse<br />

Figure weiterleiten.<br />

• Ein Konstruktor kann auch seine eigenen Attribute initialisieren.<br />

Vorgehensweise:<br />

Aufruf des Basisklassenkonstruktors.<br />

Initialisierung der eigenen Attribute.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 141


Vererbung<br />

Vererbung der Implementierung – Konstruktorenreihenfolge<br />

• Klassenelemente werden von „oben“ nach „unten“ initialisiert:<br />

<br />

<br />

<br />

Erst wird der Konstruktor der Basisklasse aufgerufen.<br />

Dann werden die Attribute einer Klasse in der Reihenfolge ihrer Deklaration initialisiert.<br />

Abschließend wird der Konstruktor der Klasse selbst aufgerufen.<br />

• Initialisierungsreihenfolge im Ghost-Beispiel:<br />

Figure<br />

-xPos: int<br />

-yPos: int<br />

+Figure()<br />

Initialisierungsreihenfolge<br />

1. Attribute der Basisklasse in der<br />

Reihenfolge ihrer Deklaration<br />

2. Konstruktor der Basisklasse<br />

Ghost<br />

-dangerous: boolean<br />

+Ghost()<br />

3. Attribute der abgeleiteten Klasse<br />

in der Reihenfolge ihrer Deklaration<br />

4. Konstruktor der abgeleiteten Klasse<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 142


Vererbung<br />

Vererbung der Implementierung – Konstruktorenreihenfolge<br />

• Beispiel: Ghost<br />

public Ghost(int xPos, int yPos, boolean dangerous) {<br />

super(xPos, yPos);<br />

this.dangerous = dangerous;<br />

}<br />

Konstruktor<br />

Basisklasse<br />

Attribute<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 143


Vererbung<br />

Vererbung der Implementierung – Freigabereihenfolge<br />

• Zur Erinnerung: Vor der Freigabe wird die Methode finalize aufgerufen.<br />

<br />

<br />

Zuerst wird finalize der abgeleiteten Klasse aufgerufen.<br />

Diese Methode ruft finalize der Basisklasse auf und führt dann eigene<br />

Aufräumarbeiten durch.<br />

• Aufrufreihenfolge der finalize-Methoden im Ghost-Beispiel (sofern dort finalize<br />

implementiert wurde):<br />

Figure<br />

-xPos: int<br />

-yPos: int<br />

#finalize()<br />

Freigabereihenfolge<br />

2. finalize der Basisklasse<br />

Ghost<br />

-dangerous: boolean<br />

#finalize()<br />

ruft auf<br />

1. finalize der abgeleiteten Klasse<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 144


Vererbung<br />

Vererbung der Implementierung - Verhindern der Vererbung<br />

• Soll verhindert werden, dass von einer bestimmten Klasse geerbt wird, dann kann sie als<br />

final deklariert werden. Beispiel:<br />

public final class Game {<br />

private Cell[][] cells;<br />

public Game() { /* ... */ }<br />

}<br />

public void run() { /* ... */ }<br />

/* ... */<br />

Die Klasse String ist beispielsweise als final deklariert.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 145


Vererbung<br />

Vererbung der Implementierung – Klassenhierarchien<br />

Bildung komplexer Klassenhierarchien<br />

Jede abgeleitete Klasse kann die Basisklasse einer anderen Klasse sein.<br />

Figure<br />

-xPos: int<br />

-yPos: int<br />

public class Figure {<br />

private int xPos;<br />

private int yPos;<br />

+Figure()<br />

Ghost<br />

-dangerous: boolean<br />

+Ghost()<br />

}<br />

public Figure() { /* ... */ }<br />

public void move(int xPos, int yPos) {<br />

/* ... */<br />

}<br />

public void print() { /* ... */ }<br />

/* ... */<br />

FlyingGhost<br />

+FlyingGhost()<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 146


Vererbung<br />

Vererbung der Implementierung – Klassenhierarchien<br />

Figure<br />

-xPos: int<br />

-yPos: int<br />

+Figure()<br />

Ghost<br />

-dangerous: boolean<br />

+Ghost()<br />

FlyingGhost<br />

public class Ghost extends Figure {<br />

private boolean dangerous;<br />

}<br />

public void move(int xPos, int yPos) {<br />

/* ... */ }<br />

public void print() { /* ... */ }<br />

/* ... */<br />

+FlyingGhost()<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 147


Vererbung<br />

Vererbung der Implementierung – Klassenhierarchien<br />

Figure<br />

-xPos: int<br />

-yPos: int<br />

+Figure()<br />

Ghost<br />

-dangerous: boolean<br />

+Ghost()<br />

FlyingGhost<br />

public class FlyingGhost extends Ghost {<br />

+FlyingGhost()<br />

}<br />

public void print() { /* ... */ }<br />

/* ... */<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 148


Vererbung<br />

Vererbung der Implementierung – Klassenhierarchien<br />

Hinweise<br />

• Die Klassenhierarchie kann einen Baum bilden.<br />

Beispiel:<br />

public class Person { /* ... */ }<br />

public class Student extends Person { /* ... */ }<br />

public class Angestellter extends Person { /* ... */ }<br />

• Mehrfachvererbung gibt es in Java nicht.<br />

Definition: Einfachvererbung<br />

Eine abgeleitete Klasse erbt nur von einer direkten Basisklasse.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 149


Vererbung<br />

Vererbung der Implementierung – Rechte bei Attribut- oder Methodenzugriffen<br />

• Neues Zugriffsrecht: protected für Vererbung räumt einer abgeleiteten Klasse mehr<br />

Rechte als einer anderen Klasse ein.<br />

• Eine abgeleitete Klasse kann<br />

<br />

<br />

<br />

alle public- oder protected-Methoden aller seiner Basisklassen aufrufen.<br />

alle public- oder protected-Attribute aller seiner Basisklassen lesen und beschreiben.<br />

nicht auf die privaten Methoden oder privaten Attribute der Basisklassen zugreifen.<br />

• Wird eine abgeleitete Klasse in einem Programm verwendet, so kann nur auf die public-<br />

Methoden oder Attribute dieser Klasse sowie deren Oberklassen zugegriffen werden.<br />

Beispiel:<br />

Ghost ghost = new Ghost(3, 2, true);<br />

ghost.move(3, 1);<br />

boolean dangerous = ghost.dangerous;<br />

// OK<br />

// Fehler, privat<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 150


Vererbung<br />

Vererbung der Implementierung – Rechte bei Attribut- oder Methodenzugriffen<br />

• Szenario:<br />

hska.iwii.my hska.iwii.p1 hska.iwii.p2<br />

public class A {<br />

public int i1;<br />

protected int i2;<br />

private int i3;<br />

int i4;<br />

}<br />

//code<br />

class B extends A {<br />

//code<br />

}<br />

class C {<br />

//code<br />

}<br />

class D extends A {<br />

//code<br />

}<br />

class E {<br />

//code<br />

}<br />

class F {<br />

}<br />

//code<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 151


Vererbung<br />

Vererbung der Implementierung – Rechte bei Attribut- oder Methodenzugriffen<br />

hska.iwii.my hska.iwii.p1 hska.iwii.p2<br />

public class A {<br />

public int i1;<br />

protected int i2;<br />

private int i3;<br />

int i4;<br />

}<br />

//code<br />

class B extends A {<br />

//code<br />

}<br />

class C {<br />

//code<br />

}<br />

class D extends A {<br />

//code<br />

}<br />

class E {<br />

//code<br />

}<br />

class F {<br />

}<br />

//code<br />

public int i1 ist in allen Klassen und Paketen sichtbar.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 152


Vererbung<br />

Vererbung der Implementierung – Rechte bei Attribut- oder Methodenzugriffen<br />

hska.iwii.my hska.iwii.p1 hska.iwii.p2<br />

public class A {<br />

public int i1;<br />

protected int i2;<br />

private int i3;<br />

int i4;<br />

}<br />

//code<br />

class B extends A {<br />

//code<br />

}<br />

class C {<br />

//code<br />

}<br />

class D extends A {<br />

//code<br />

}<br />

class E {<br />

//code<br />

}<br />

class F {<br />

}<br />

//code<br />

protected int i2 ist in Unterklassen und im eigenen Paket sichtbar.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 153


Vererbung<br />

Vererbung der Implementierung – Rechte bei Attribut- oder Methodenzugriffen<br />

hska.iwii.my hska.iwii.p1 hska.iwii.p2<br />

public class A {<br />

public int i1;<br />

protected int i2;<br />

private int i3;<br />

int i4;<br />

}<br />

//code<br />

class B extends A {<br />

//code<br />

}<br />

class C {<br />

//code<br />

}<br />

class D extends A {<br />

//code<br />

}<br />

class E {<br />

//code<br />

}<br />

class F {<br />

}<br />

//code<br />

private int i3 ist nur in der eigenen Klasse sichtbar.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 154


Vererbung<br />

Vererbung der Implementierung – Rechte bei Attribut- oder Methodenzugriffen<br />

hska.iwii.my hska.iwii.p1 hska.iwii.p2<br />

public class A {<br />

public int i1;<br />

protected int i2;<br />

private int i3;<br />

int i4;<br />

}<br />

//code<br />

class B extends A {<br />

//code<br />

}<br />

class C {<br />

//code<br />

}<br />

class D extends A {<br />

//code<br />

}<br />

class E {<br />

//code<br />

}<br />

class F {<br />

}<br />

//code<br />

• int i4 ist im eigenen Package sichtbar.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 155


Überschreiben von Methoden<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 156


Überschreiben von Methoden<br />

Grundlagen<br />

• Idee: Eine abgeleitete Klasse besitzt eine Methode mit demselben Namen und derselben<br />

Signatur wie die Basisklasse.<br />

Basisklasse<br />

+print()<br />

AbgeleiteteKlasse<br />

+print()<br />

• Ein häufiges Problem beim Prinzip der Ersetzbarkeit:<br />

<br />

<br />

Eine Basisklassenreferenz verweist auf ein Objekt einer abgeleiteten Klasse.<br />

Wie kann festgestellt werden, welcher Klasse das Objekt angehört wichtig für den<br />

Aufruf der korrekten Methode?<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 157


Überschreiben von Methoden<br />

Grundlagen<br />

Definition: Überschreiben (von Methoden)<br />

• Wenn eine abgeleitete Klasse eine Methode implementiert, für die es bereits in einer<br />

Basisklasse eine Methode gibt, so überschreibt die abgeleitete Klasse die Methode der<br />

Basisklasse.<br />

• Wird die Operation auf einem Exemplar der abgeleiteten Klasse aufgerufen, so wird die<br />

überschriebene Implementierung der Methode aufgerufen.<br />

• Das ist unabhängig davon, welchen Typ die Referenz hat, über die das Objekt angesprochen<br />

wird.<br />

• Entscheidend ist der Typ des Objekts selbst, nicht der Typ der Variablen.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 158


Überschreiben von Methoden<br />

Grundlagen<br />

• Aufruf der neuen Methode print.<br />

public class Figure {<br />

public void print() {<br />

System.out.println("Figure");<br />

}<br />

}<br />

public class Ghost extends Figure {<br />

private boolean dangerous;<br />

@Override<br />

public void print() {<br />

System.out.println("Ghost");<br />

}<br />

}<br />

// …<br />

private int test() {<br />

Ghost ghost = new Ghost(3, 2, true);<br />

Figure figure = ghost;<br />

ghost.print();<br />

figure.print();<br />

// ...<br />

Figure<br />

-xPos: int<br />

-yPos: int<br />

+print()<br />

Ghost<br />

-dangerous: boolean<br />

+print()<br />

Ausgabe:<br />

Ghost<br />

Ghost<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 159


Überschreiben von Methoden<br />

Verhalten<br />

Verhalten<br />

• Aufruf der Methode der abgeleiteten Klasse (auch, wenn die Methode über eine<br />

Basisklassenreferenz aufgerufen wird).<br />

• Vorteil: Code, der die Methoden aufruft, bleibt unverändert, selbst wenn Klassen<br />

hinzukommen oder sich Klassen ändern.<br />

• Verhalten<br />

Alle Methoden, die nicht als final deklariert werden, können überschrieben werden.<br />

Signatur und Name der Methode müssen in Basisklasse und abgeleiteter Klasse identisch<br />

sein.<br />

• Überschreibende Methoden sollten mit der Annotation @Override versehen werden. Dann<br />

kann der Compiler prüfen, ob diese Methode wirklich eine andere überschreibt:<br />

public class Ghost extends Figure {<br />

@Override<br />

public void print() {<br />

System.out.println("Ghost");<br />

}<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 160


Überschreiben von Methoden<br />

Verhalten<br />

• Beispiel für eine Methode, die nicht überschrieben werden darf:<br />

public class Figure {<br />

public final void print() {<br />

System.out.println("Figure");<br />

}<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 161


Überschreiben von Methoden<br />

Manueller Einfluss<br />

Manueller Einfluss auf das Überschreiben<br />

• Umgehung der automatischen Methodenauswahl, expliziter Aufruf einer Methode der<br />

Basisklasse: super.methode(Parameter);<br />

Beispiel:<br />

public class Figure {<br />

// ...<br />

public void move(int xPos, int yPos) {<br />

// ...<br />

}<br />

}<br />

-xPos: int<br />

-yPos: int<br />

Figure<br />

+move(xPos: int, yPos: int)<br />

public class Ghost extends Figure {<br />

// ...<br />

@Override<br />

public void move(int xPos, int yPos) {<br />

super.move(xPos, yPos);<br />

// z.B. Neuzeichnen<br />

}<br />

}<br />

Ghost<br />

-dangerous: boolean<br />

+move(xPos: int, yPos: int)<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 162


Überschreiben von Methoden<br />

Konstruktoren<br />

Konstruktoren und Überschreiben<br />

• Der Konstruktor der Basisklasse wird vor dem Konstruktor der abgeleiteten Klasse<br />

ausgeführt.<br />

• Aufruf einer polymorphen Methode im Konstruktor der Basisklasse:<br />

Im Gegensatz zu C++: Aufruf der überschriebenen Methode<br />

Achtung: Die abgeleitete Klasse ist noch gar nicht initialisiert!!<br />

Konsequenz: Konstruktoren sollten nur private oder finale Methoden aufrufen.<br />

nein<br />

public class Base {<br />

private Bruch br;<br />

public Base() {<br />

}<br />

br = new Bruch();<br />

init();<br />

}<br />

public void init() {<br />

br.setZaehler(42);<br />

}<br />

ja<br />

public class Derived<br />

extends Base {<br />

private MathVector mv;<br />

public Derived() {<br />

mv = new MathVector(3,true);<br />

init();<br />

}<br />

@Override<br />

public void init() {<br />

mv.setValue(0, 66);<br />

}<br />

}<br />

Base<br />

+Base()<br />

+init()<br />

Derived<br />

+Derived()<br />

+init()<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 163


Überschreiben von Methoden<br />

Hinweise<br />

Hinweise zum Umgang mit dem Überschreiben<br />

Ermittlung der „richtigen“ Methode:<br />

• Zur Übersetzungszeit (early binding, statische Bindung):<br />

Der Aufruf kann vom Compiler direkt in Bytecode umgesetzt werden, da die Methode<br />

jederzeit bekannt ist.<br />

nur für Methoden möglich, die als final oder private deklariert sind<br />

• Zur Laufzeit (late binding, dynamische Bindung):<br />

Alle Methoden, die nicht final, nicht privat und nicht statisch sind Polymorphismus.<br />

Das Objekt findet selbst heraus, welche Methode aufgerufen werden soll<br />

geringer Mehraufwand beim Methodenaufruf<br />

Die überschreibende Methode der abgeleiteten Klasse darf die Zugriffsrechte der<br />

Methode der Basisklasse nicht einschränken.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 164


Überschreiben von Methoden<br />

Hinweise<br />

Hinweise zum Design<br />

• „Normale“ Methoden:<br />

<br />

<br />

Alle Methoden einer Klasse, die überschrieben werden dürfen, sollten nicht final sein.<br />

final sollte nur aus Design- nicht aus Geschwindigkeitsgründen hinzugefügt werden.<br />

• Finale Methoden:<br />

<br />

Methoden, die nicht überschrieben werden dürfen, sollten als final deklariert werden.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 165


Überschreiben von Methoden<br />

Regeln<br />

• Wiederholung: Prinzip der Ersetzbarkeit<br />

• Wenn die Klasse Abgel eine abgeleitete Klasse der Klasse Basis ist, dann können in einem<br />

Programm alle Objekte der Klasse Basis durch Objekte der Klasse Abgel ersetzt worden<br />

sein, und es gelten trotzdem weiterhin alle zugesicherten Eigenschaften der Klasse Basis.<br />

• Der für die Basisklasse geschlossene Kontrakt mit Bezug auf Vorbedingungen,<br />

Nachbedingungen und Invarianten gilt also auch dann weiter, wenn Objekte der Basisklasse<br />

durch Objekte der abgeleiteten Klasse ersetzt werden.<br />

• Beim Überschreiben von Methoden gilt also: Abgeleitete Klassen dürfen zwar mehr anbieten,<br />

aber nicht mehr verlangen als Exemplare ihrer Basisklassen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 166


Überschreiben von Methoden<br />

Regeln<br />

Liskovsches Substitutionsprinzip<br />

Formulierung 1993 von Barbara Liskov und Jeannette Wing:<br />

• Basisklasse Basis<br />

• b ist ein Objekt von Basis.<br />

• Abgeleitete Klasse Abgeleitet,<br />

die von Basis erbt<br />

• a ist ein Objekt von Abgeleitet.<br />

• Es gilt:<br />

Sei q(b) eine beweisbare Eigenschaft von Objekten b des Typs Basis. Dann soll q(a) für<br />

Objekte a des Typs Abgeleitet wahr sein.<br />

• Beispiele kommen gleich!<br />

Basis<br />

Abgeleitet<br />

Besser verständlich als „ist-ein“-Beziehung.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 167


Überschreiben von Methoden<br />

Regeln<br />

• Konsequenzen für die Vorbedingungen, Nachbedingungen und Invarianten einer<br />

abgeleiteten Klasse:<br />

Schwächere Vorbedingungen:<br />

- Eine abgeleitete Klasse kann die Vorbedingungen für eine Operation, die durch die<br />

Basisklasse definiert wird, einhalten oder abschwächen. Sie darf die Vorbedingungen<br />

aber nicht verschärfen.<br />

- Falls eine abgeleitete Klasse die Vorbedingungen verschärfen würde, würde damit<br />

ohne Absprache mit den Partnern von diesen mehr verlangt als vorher.<br />

- Erlaubte und verbotene Maßnahmen (unvollständig):<br />

Der Wertebereich der Übergabeparameter wird erweitert.<br />

Eine nicht öffentliche Methode wird öffentlich überschrieben.<br />

Der Wertebereich der Übergabeparameter wird verkleinert.<br />

Der Übergabeparameter wird von einem Objekt der Basisklasse auf ein Objekt<br />

der abgeleiteten Klasse eingeschränkt.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 168


Überschreiben von Methoden<br />

Regeln<br />

<br />

Stärkere Nachbedingungen:<br />

- Eine abgeleitete Klasse kann die Nachbedingungen für eine Operation, die durch<br />

eine Oberklasse definiert werden, einhalten oder einschränken. Sie darf die<br />

Nachbedingungen aber nicht lockern.<br />

- Falls eine abgeleitete Klasse die Nachbedingungen lockern würde, würde diesen<br />

damit wieder ohne Absprache mit den Partnern des Kontrakts mehr geboten als<br />

vorher.<br />

- Erlaubte und verbotene Maßnahmen (unvollständig):<br />

Der Wertebereich der Rückgabeergebnisse wird eingeschränkt.<br />

Der Rückgabetyp ist ein Objekt der abgeleiteten Klasse A (A erbt von B),<br />

während die Methode der Basisklasse ein Objekt einer Basisklasse B zurückgibt.<br />

Der Wertebereich der Rückgabeergebnisse wird erweitert.<br />

Der Rückgabetyp ist ein Objekt der Basisklasse B, während die Methode der<br />

Basisklasse ein Objekt einer abgeleiteten Klasse A (A erbt von B) zurückgibt.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 169


Überschreiben von Methoden<br />

Regeln<br />

<br />

Invarianten:<br />

- Eine abgeleitete Klasse muss dafür sorgen, dass die für die Basisklasse definierten<br />

Invarianten immer gelten. Sie darf die Invarianten verschärfen.<br />

- Die Partner des Kontrakts müssen sich auf die zugesicherten Invarianten verlassen<br />

können.<br />

- Eine Verhaltensänderung darf eintreten.<br />

Ergebnis: Design by Contract<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 170


Überschreiben von Methoden<br />

Regeln<br />

• Beispiel für die Verletzung der Ersetzbarkeit:<br />

context Rectangle::scaleX(factor: float)<br />

pre: factor > 0<br />

post: (lengthX = lengthX@pre * factor<br />

and lengthY = lengthY@pre)<br />

context Square<br />

inv: lengthX = lengthY<br />

+display()<br />

Figure<br />

Rectangle<br />

-lengthX: int<br />

-lengthY: int<br />

+display()<br />

+scaleX(factor: double)<br />

+scaleY(factor: double)<br />

Square<br />

Ersetzbarkeit verletzt:<br />

Neue Einschränkung<br />

der Längen in der<br />

Invariante des<br />

Quadrates!<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 171


Überschreiben von Methoden<br />

Regeln<br />

• Beispiel für die Einhaltung der Ersetzbarkeit:<br />

context Account::withdraw<br />

pre: amount > 0 and amount 0<br />

and amount


Überschreiben von Methoden<br />

Regeln<br />

• Implementierung des Kontobeispiels:<br />

public class Account {<br />

private int balance = 0;<br />

}<br />

public int getBalance() {<br />

return balance;<br />

}<br />

public void withdraw(int amount) {<br />

assert amount > 0<br />

&& amount 0<br />

&& amount


Überschreiben von Methoden<br />

Regeln<br />

• Verwendung des Kontobeispiels:<br />

CreditAccount account1 = new CreditAccount(10000);<br />

Account account2 = new Account();<br />

// Abheben<br />

bank.withdraw(account1);<br />

bank.withdraw(account2);<br />

// Methode zum Abheben eines Festbetrags<br />

// account verweist auf Account oder CreditAccount<br />

public void withdraw(Account accountPtr) {<br />

if (accountPtr.getBalance() >= 200)<br />

accountPtr.withdraw(200);<br />

}<br />

• Wichtig: In der Methode withdraw sind Vor- und Nachbedingung sowie Invariante nur<br />

anhand der Klasse Account erkennbar!<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 174


Überschreiben von Methoden<br />

Regeln<br />

• Beispiel für die Verletzung der Ersetzbarkeit (Einschränkung der Vorbedingung):<br />

context Account::transfer<br />

pre: amount > 0 and amount


Überschreiben von Methoden<br />

Regeln<br />

• Implementierung des Kontobeispiels (unvollständig):<br />

public class Account {<br />

private int balance = 0;<br />

private int creditLimit = 0;<br />

public class DepositAccount extends<br />

Account {<br />

}<br />

public int getBalance() {<br />

return balance;<br />

}<br />

public void transfer(int amount,<br />

Account dest) {<br />

assert amount > 0<br />

&& amount 0;<br />

balance += amount;<br />

}<br />

}<br />

@Override<br />

public void transfer(int amount,<br />

Account dest) {<br />

assert false;<br />

}<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 176


Überschreiben von Methoden<br />

Regeln<br />

• Verwendung des Kontobeispiels:<br />

DepositAccount account1 = new DepositAccount();<br />

Account account2 = new Account();<br />

// Überweisen<br />

bank.transfer(account1, account2);<br />

bank.transfer(account2, account1);<br />

// Methode zum Überweisen eines Festbetrags<br />

public void transfer(Account dest, Account source) {<br />

if (source.getBalance() + source.getCreditLimit() >= 200)<br />

source.transfer(200, dest);<br />

}<br />

• Wichtig: In der Methode transfer berücksichtigt die Vorbedingung der Klasse Account.<br />

DepositAccount schränkt diese aber ein Methode transfer kann nicht richtig<br />

funktionieren.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 177


Überschreiben von Methoden<br />

Regeln<br />

• Problem: Die Kontraktverletzungen werden erst zur Laufzeit entdeckt vollständige Test<br />

erforderlich.<br />

• Lösung: Spracherweiterungen, die eine Spezifikation der Kontrakte erlauben<br />

• Problem: Prüfungen auf Kontrakteinhaltung müssen manuell in den Code verteilt werden <br />

sehr viel Arbeit.<br />

• Lösung: AOP (Aspect Oriented Programming) kommt später<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 178


Überschreiben von Methoden<br />

Regeln<br />

• Wie können Kontrakte angegeben werden?<br />

<br />

<br />

<br />

in UML mit OCL<br />

im Quelltext mit Assertions (auch mit Hilfe von AOP)<br />

Es gibt Erweiterungen objektorientierter Sprachen um Constraints, Auswahl:<br />

jContractor (http://jcontractor.sourceforge.net/),<br />

C4J (http://c4j.sourceforge.net/),<br />

COFOJA (http://code.google.com/p/cofoja)<br />

• Wie sieht es bei Schnittstellen oder abstrakten Klassen aus? Dort gibt es keine<br />

Implementierung!<br />

in UML mit OCL spezifizieren<br />

im Quelltext dokumentieren<br />

Constraint-Erweiterung verwenden<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 179


Überschreiben von Methoden<br />

Kovarianz und Kontravarianz<br />

Genauerer Blick auf die Vererbung bei Methodenparametern und Rückgabetypen<br />

• Kovariante Rückgabetypen in der clone-Methode: Der Rückgabetyp in der abgeleiteten<br />

Klasse erbt vom Rückgabetyp der Basisklasse<br />

Figure<br />

-x: int<br />

-y: int<br />

+clone(): Figure<br />

Ghost<br />

Die Klasse T2 ist der Klasse T1 kovariant,<br />

wenn alle Objekte von T2 gleichzeitig<br />

Objekte von T1 sind.<br />

Einfacher gesagt: T2 muss entweder T1<br />

oder eine abgeleitete Klasse sein.<br />

+clone(): Ghost<br />

<br />

<br />

<br />

Einschränkung der Nachbedingung in dieser Form ist erlaubt.<br />

Java unterstützt seit Version 5 kovariante Rückgabetypen.<br />

C++ hat kovariante Rückgabetypen im Standard definiert. Allerdings unterstützen nicht<br />

alle Compiler dieses Sprachmittel.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 180


Überschreiben von Methoden<br />

Kovarianz und Kontravarianz<br />

• Kovariante Übergabetypen in der set-Methode: Der Übergabegabetyp in der abgeleiteten<br />

Klasse erbt vom Übergabegabetyp der Basisklasse<br />

-x: int<br />

-y: int<br />

Figure<br />

+set(f: Figure)<br />

Ghost<br />

+set(g: Ghost)<br />

<br />

<br />

<br />

Die Einschränkung der Vorbedingung ist nicht erlaubt.<br />

Ausweg: In Java und C++ wird die Methode set in Figure gar nicht überschrieben, sie<br />

wird überladen!<br />

Schlussfolgerung: Die Übergabetypen sind nicht kovariant.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 181


Überschreiben von Methoden<br />

Kovarianz und Kontravarianz<br />

• Kontravariante Übergabetypen in der set-Methode: Der Übergabegabetyp in der<br />

abgeleiteten Klasse ist Basisklasse des Übergabetyps der Basisklasse<br />

-x: int<br />

-y: int<br />

Figure<br />

+set(g: Ghost)<br />

Ghost<br />

Die Klasse T2 ist der Klasse T1 kontravariant,<br />

wenn alle Objekte von T1 gleichzeitig<br />

Objekte von T2 sind.<br />

Einfacher gesagt: T1 muss entweder T2<br />

oder seine abgeleitete Klasse sein.<br />

+set(f: Figure)<br />

<br />

<br />

Aufweichung der Vorbedingung ist erlaubt.<br />

Kontravariante Übergabetypen sind erlaubt.<br />

• Kontravariante Rückgabetypen sind nicht erlaubt.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 182


Vererbung<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 183


Vererbung<br />

Vererbung der Implementierung (abstrakte Basisklasse)<br />

Spezialfall der Vererbung: Abstrakte Basisklasse<br />

• Idee: Es gibt keine Objekte der Oberklasse. Alle Objekte der Basisklasse müssen durch<br />

Unterklassenobjekte repräsentiert werden.<br />

• Beispiel: Ein Konto ist entweder ein Girokonto oder ein Sparkonto.<br />

• Es muss eines von beiden sein, kann aber nicht in beiden Klassen gleichzeitig sein.<br />

• Pacman-Beispiel: Es gibt keine Objekte der Basisklasse Figure.<br />

Figure<br />

kursiv<br />

Ghost<br />

Pacman<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 184


Vererbung<br />

Vererbung der Implementierung (abstrakte Basisklasse)<br />

• Klassen werden mit dem Schlüsselwort abstract als abstrakt markiert, um zu verhindern,<br />

dass ein Objekt solcher Klasse erzeugt wird.<br />

• Beispiel: Figure, von dem keine Objekte erzeugt werden dürfen.<br />

public abstract class Figure {<br />

private int xPos;<br />

private int yPos;<br />

}<br />

public void handleCollisionWith(Figure other){<br />

// ...<br />

}<br />

public class Pacman extends Figure {<br />

private boolean mouthOpening;<br />

}<br />

@Override<br />

public void handleCollisionWith(Figure other) {<br />

// ...<br />

}<br />

// ...<br />

Überschreiben bzw.<br />

implementieren der Methode<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 185


Vererbung<br />

Vererbung der Implementierung (abstrakte Basisklasse)<br />

• Auch Methoden können abstrakt sein:<br />

<br />

<br />

<br />

Die Basisklasse kann z.B. keine sinnvolle gemeinsame Implementierung anbieten.<br />

Die abgeleiteten Klassen müssen die Methoden dann implementieren.<br />

Ein Klasse mit mindestens einer abstrakten Methode ist abstrakt.<br />

• Beispiel: Figure ohne Implementierung des Zeichnens<br />

public abstract class Figure {<br />

private boolean dead;<br />

}<br />

public abstract void paint(JComponent panel);<br />

// ...<br />

keine Implementierung<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 186


Vererbung<br />

Vererbung der Spezifikation (Schnittstellen)<br />

• Für die Vererbung einer Spezifikation gibt es in Java Schnittstellen (interface).<br />

• Es werden nur Methodensignaturen und statische Attribute angeboten, ohne irgendwelche<br />

Implementierungsdetails bekannt zugeben.<br />

• Beispiel: Schnittstelle Runnable aus dem JDK<br />

public interface Runnable {<br />

void run();<br />

}<br />

• Alle Methoden sind public (nicht angegeben).<br />

• Alle Attribute sind public, static und final<br />

(nicht angegeben).<br />

• Implementierung einer Schnittstelle:<br />

public class Figure implements Runnable {<br />

@Override<br />

public void run() { /* ... */ }<br />

}<br />

<br />

Runnable<br />

+run()<br />

Figure<br />

-xPos: int<br />

-yPos: int<br />

+run()<br />

• Eine Klasse darf beliebig viele Schnittstellen direkt implementieren (die Schnittstellen werden<br />

mit Kommata getrennt aufgeführt).<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 187


Vererbung<br />

Beispiel: „Pacman“<br />

• Ziel: Klassenhierarchie für das Zeichenprogramm oder Pacman-Figuren<br />

• Die Algorithmen des Programms sollen auch mit noch „unbekannten“ Figuren funktionieren<br />

Erweiterbarkeit!<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 188


Generische Klassen<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 189


Generische Klassen<br />

Definition: Generische Klasse<br />

Eine generische Klasse ist eine mit formalen generischen Parametern versehene Schablone.<br />

Erst durch die Verwendung der Klasse werden die Parameter durch konkrete Klassen ersetzt.<br />

So kann zur Übersetzungszeit eine höhere Typsicherheit sichergestellt werden.<br />

Darstellung mit UML:<br />

TemplateKlasse<br />

T: class Parametertyp<br />

Parametername<br />

• Parameteraufbau: Parameter-Name[:Parameter-Typ][=Vorgabewert]<br />

<br />

<br />

<br />

Parameter-Name: Name des Platzhalters<br />

Parameter-Typ: Optionale Klasse des Parameters. Ist kein Typ angegeben, kann jede<br />

beliebige Klasse class verwendet werden.<br />

Vorgabewert: Standardwert, falls die Typangabe fehlt<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 190


Generische Klassen<br />

Vektor (Version 3)<br />

• Vektor als generische Klasse:<br />

public class Vector {<br />

private E[] values;<br />

@SuppressWarnings("unchecked")<br />

public Vector(int size, E initValue) {<br />

values = (E[]) new Object[ size ];<br />

for (int i = 0; i < size; ++i) {<br />

values[ i ] = initValue;<br />

}<br />

}<br />

public void setValue(int index, E value) {<br />

values[ index ] = value;<br />

}<br />

Vector<br />

- values: E[*] {bag}<br />

+ Vector(size: int, initValue: E)<br />

+ setValue(index: int, value: E)<br />

+ getValue(index: int): E<br />

E: class<br />

}<br />

public E getValue(int index) {<br />

return values[ index ];<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 191


Generische Klassen<br />

• Anmerkungen:<br />

<br />

<br />

<br />

<br />

<br />

public class Vector: ist der Platzhalter für eine Klasse.<br />

Der Platzhalter steht immer für den Namen einer Klasse oder Schnittstelle:<br />

- Primitive Datentypen werden nicht unterstützt.<br />

- Intern speichert die Klasse Referenzen vom Typ Object ab.<br />

- Der Platzhalter dient zum typsicheren Zugriff, der zur Übersetzungszeit geprüft<br />

werden kann.<br />

- Der Platzhaltertyp kann fast wie ein normaler Datentyp innerhalb der Klasse<br />

verwendet werden. Ausnahmen: Objekterzeugung, Arrays<br />

Der cast-Operator im Konstruktor ist nicht geprüft. Deshalb wird die Warnung des<br />

Compilers mit @SuppressWarnings("unchecked") unterdrückt.<br />

In Java können keine Arrays mit generischen Typen angelegt werden. Deshalb erzeugt<br />

der Vektor Object-Arrays kommt noch genauer.<br />

Es dürfen mehrere Platzhalter verwendet werden. Beispiel:<br />

public class HashMap { /* … */ }<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 192


Generische Klassen<br />

• Eine konkrete Instanz einer generischen Klasse wird durch die folgende Schreibweise<br />

erzeugt: Klasse<br />

• Beispiel:<br />

Vector vector1 = new Vector(3, 0.0);<br />

Kann anhand des Typs der Referenz erkannt werden.<br />

• Beispiel (der Compiler stellt sicher, dass die rot markierten Elemente vom Typ Double bzw.<br />

double sind):<br />

Vector v1 = new Vector(3, 0.0);<br />

v1.setValue(0, 2.0);<br />

double value = v1.getValue();<br />

System.out.println(value);<br />

• Beispiel ohne generische Klasse (der Compiler kann keine Typprüfung vornehmen):<br />

Vector v1 = new Vector(3, 0.0);<br />

v1.setValue(0, 2.0);<br />

Double value = (Double) v1.getValue();<br />

System.out.println(value);<br />

Falsche Werte (z.B. String) werden zur Laufzeit bemerkt (ClassCastException).<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 193


Generische Klassen<br />

Umsetzung in der virtuellen Maschine<br />

• Generische Klassen wurden erst mit Java 5 eingeführt.<br />

• Ziel war es, den Bytecode zu Java 1.4 kompatibel zu halten.<br />

• Wie lassen sich generische Klassen implementieren?<br />

<br />

heterogen: Für jeden Typparameter wird eine neue Klasse erzeugt (C++-Ansatz).<br />

homogen: Es wird nur eine Klasse erzeugt. Der Typparameter wird durch die oberste<br />

Basisklasse Object ersetzt. Die Typparameter dienen nur zur Prüfung während der<br />

Übersetzungszeit (Java-Ansatz).<br />

• Der Compiler löscht also die Typ-Informationen („type erasure“):<br />

Der Bytecode bleibt kompatibel zu Java 1.4.<br />

Die generischen Typen existieren nicht mehr zur Laufzeit führt zu Problemen:<br />

Vector v1 = new Vector();<br />

if (v1 instanceof Vector) // Compilerfehler, da Vector zur<br />

// Laufzeit nicht existiert!<br />

Korrekt wäre:<br />

Vector v1 = new Vector();<br />

if (v1 instanceof Vector) // Vector existiert<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 194


Generische Klassen<br />

Umsetzung in der virtuellen Maschine<br />

<br />

Damit sind die Klassen trotz unterschiedlicher Typparameter identisch:<br />

Vector v1 = new Vector();<br />

Vector v2 = new Vector();<br />

if (v1.getClass() == v2.getClass()) // true<br />

• Generische Klassen lassen sich auch ohne Typparameter verwenden („raw type“):<br />

Vector v1 = new Vector();<br />

Vector v2 = new Vector();<br />

Die Verwendung führt aber z.B. bei setValue zu einer Compiler-Warnung.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 195


Generische Klassen<br />

Umsetzung in der virtuellen Maschine<br />

• Beispiel für die Umsetzung anhand des Vektors (Ausschnitt):<br />

Definition im Quelltext<br />

public class Vector {<br />

private E[] values;<br />

Definition zur Laufzeit („fiktiv“)<br />

public class Vector {<br />

private Object[] values;<br />

// ...<br />

// ...<br />

public void setValue(int index, E value) {<br />

values[ index ] = value;<br />

}<br />

public void setValue(int index, Object value) {<br />

values[ index ] = value;<br />

}<br />

}<br />

public E getValue(int index) {<br />

return values[ index ];<br />

}<br />

}<br />

public Object getValue(int index) {<br />

return values[ index ];<br />

}<br />

Verwendung im Quelltext<br />

Vector names = new Vector();<br />

names.setValue(0, "Vogelsang");<br />

String name = names.getValue(0);<br />

Verwendung zur Laufzeit („fiktiv“)<br />

Vector names = new Vector();<br />

names.setValue(0, "Vogelsang");<br />

String name = (String) names.getValue(0);<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 196


Generische Klassen<br />

Arrays<br />

• Arrays mit generischen Typen haben einige Besonderheiten:<br />

<br />

<br />

Die Deklaration ist problemlos möglich:<br />

private ArrayList[] al;<br />

Aber eine Initialisierung klappt nicht intuitiv:<br />

private ArrayList[] al = new ArrayList[ 10 ];<br />

// Compilerfehler<br />

• Lösungen:<br />

Verwendung des Platzhalters ?:<br />

<br />

private ArrayList[] al<br />

= (ArrayList[]) new ArrayList[ 10 ];<br />

Erstellen einer Klasse für den Inhalt der Arrayzellen:<br />

public class MyList extends ArrayList {<br />

// notwendige Konstruktoren<br />

}<br />

private MyList[] al = new MyList[ 10 ];<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 197


Generische Methoden<br />

• „Normale“ (nicht-generische) und generische Klassen dürfen generische Methoden besitzen.<br />

• Das wird häufig bei Hilfsklassen mit statischen Methoden eingesetzt:<br />

• Beispiel: Methode asArrayList erzeugt aus einer variablen Anzahl Übergabewerte eine<br />

ArrayList (angelehnt an Klasse Arrays aus dem SDK)<br />

public class Arrays {<br />

@SafeVarargs<br />

public static ArrayList asArrayList(T... a) {<br />

ArrayList result = new ArrayList(a.length);<br />

for (int i = 0; i < a.length; ++i) {<br />

result.add(a[ i ]);<br />

}<br />

return result;<br />

}<br />

}<br />

• Syntax: Zugriffsrecht Rückgabetyp Methodenname(Parameter)<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 198


Generische Methoden<br />

Einschränkungen der Parametertypen<br />

• Die Typparameter lassen sich einschränken:<br />

Basisklasse: Der Parametertyp muss von einer bestimmten oder mehreren Basisklassen<br />

erben.<br />

Schnittstellen: Der Parametertyp muss eine bestimmte oder mehrere Schnittstellen<br />

implementieren.<br />

• Beispiel, in dem der Vektor nur mit Klassen, die von Number erben, verwendet werden darf<br />

(weil der Vektor z.B. Zahlenoperationen durchführt), Vektor Version 4:<br />

public class Vector {<br />

private Number[] values;<br />

}<br />

public double getSum() { // Summe alle Werte ermitteln<br />

double sum = 0.0;<br />

for (int i = 0; i < values.length; ++i) {<br />

sum += values[ i ].doubleValue();<br />

}<br />

return sum;<br />

}<br />

// ...<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML<br />

199


Generische Methoden<br />

Einschränkungen der Parametertypen<br />

• Es können auch mehrere Einschränkungen vorhanden sein.<br />

• Bespiel: Der Typparameter des Vektors muss von Number erben und Cloneable<br />

implementieren:<br />

public class Vector<br />

• Syntax bei mehr als zwei Einschränkungen:<br />

public class Klasse<br />

• Achtung bei Vererbung:<br />

Vector ist keine Basisklasse von Vector!<br />

Vector v1 = new Vector(); // Compilerfehler!<br />

Ansonsten ließe sich z.B. ein String in dem Vektor speichern.<br />

Die Methode<br />

public void dump(Vector v1)<br />

darf nicht mit einem Vector aufgerufen werden.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 200


Generische Methoden<br />

Parametertypen und Vererbung<br />

• Ausweg: Wildcards erlauben es, einen Typ unbestimmt zu lassen. Beispiel:<br />

public void dump(Vector v1)<br />

<br />

<br />

? ist ein unbekannter Typ, nicht Object.<br />

Die Methode dump darf jetzt mit jedem beliebigen Typparameter verwendet werden.<br />

• Wildcards unterstützen auch Typeinschränkungen („upper bound wildcards“):<br />

public void dump(Vector


Aufzähltypen<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 202


Aufzähltypen<br />

Einführung<br />

• Ein Aufzähltyp ist eine spezielle Klasse, von der benannte Objekte erzeugt werden.<br />

Beispiel für die Bewegungsrichtungen von Figuren in Pacman:<br />

public enum Direction {<br />

NONE, UP, DOWN, LEFT, RIGHT;<br />

}<br />

• Daraus erzeugt der Compiler eine Klasse, die ungefähr so aussieht:<br />

public class Direction extends Enum {<br />

public static final Direction NONE = new Direction("NONE", 0);<br />

public static final Direction UP = new Direction("UP", 1);<br />

public static final Direction DOWN = new Direction("DOWN", 2);<br />

public static final Direction LEFT = new Direction("LEFT", 3);<br />

public static final Direction RIGHT = new Direction("RIGHT", 4);<br />

<br />

Direction<br />

NONE<br />

UP<br />

DOWN<br />

LEFT<br />

RIGHT<br />

private Direction(String name, int index) {<br />

super(name, index);<br />

}<br />

// Alle Werte ermitteln<br />

public static Direction[] values() { /* ... */ }<br />

}<br />

// weitere Methoden ...<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 203


Aufzähltypen<br />

Einführung<br />

• Vorteil von Aufzähltypen gegenüber finalen int-Werten:<br />

<br />

<br />

<br />

In einem switch-Block kann der Compiler testen, ob alle Werte eines Typs einen case-<br />

Block haben.<br />

Der Benutzer kann anhand des Typs dessen Bedeutung erkennen.<br />

Der Typ kann nur die erlaubten Werte annehmen.<br />

• Was bietet die Basisklasse Enum noch (Auswahl)?<br />

<br />

<br />

<br />

public String name(): Name des Aufzählwertes (z.B. "LEFT")<br />

Beispiel: String name = Direction.LEFT.name();<br />

public ordinal(): Index eines Wertes in der Aufzählung (z.B. 3 für der Wert<br />

Direction.LEFT, weil LEFT als dritter Wert angegeben ist)<br />

Beispiel: int index = Direction.LEFT.ordinal();<br />

public static valueOf(Class enumType,<br />

String name): Ermittelt aus dem Namen den Aufzählwert<br />

Beispiel: Direction dir = Enum.valueOf(Direction.class, "UP");<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 204


Aufzähltypen<br />

Einführung<br />

• Ein Aufzähltyp kann in Pacman für zwei Aufgaben eingesetzt werden:<br />

<br />

<br />

Richtung, in die sich eine Figur bewegt<br />

public enum Direction {<br />

NONE, UP, DOWN, LEFT, RIGHT;<br />

}<br />

Position einer Zelle, an der sich ein Rahmen befindet.<br />

- Problem: Eine Zelle kann an mehr als einer Position einen Rahmen haben.<br />

- Lösung: Bitkombination als zusätzlichen Wert dem Aufzähltyp übergeben ersetzt<br />

nicht den Index (Aufruf ordinal()).<br />

public enum Direction { // noch unvollständig<br />

NONE(0), UP(1), DOWN(2), LEFT(4), RIGHT(8), ALL(15);<br />

}<br />

• Die zweite Variante wird auch für die Richtung verwendet, wobei ALL unsinnig ist.<br />

• Beispiele:<br />

LEFT | UP | DOWN<br />

RIGHT<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 205


Aufzähltypen<br />

Methoden und Attribute<br />

• Wie funktioniert die Übergabe zusätzlicher Parameter an einen Aufzählwert genau? Dieses<br />

Beispiel ergibt Übersetzungsfehler, weil der entsprechende Konstruktor fehlt:<br />

public enum Direction {<br />

NONE(0), UP(1), DOWN(2), LEFT(4), RIGHT(8), ALL(15);<br />

}<br />

• Aufzähltypen dürfen zusätzliche Konstruktoren, Attribute und Methoden erhalten:<br />

public enum Direction {<br />

NONE(0), UP(1), DOWN(2), LEFT(4), RIGHT(8), ALL(15);<br />

private int value;<br />

protected Direction(int value) {<br />

this.value = value<br />

}<br />

Konstruktoraufruf<br />

public int getValue() {<br />

return value;<br />

}<br />

}<br />

// weitere Methoden<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 206


Aufzähltypen<br />

Methoden und Attribute<br />

• Aufzähltypen dürfen auch Schnittstellen implementieren.<br />

• Sie können aber nicht von Klassen erben, weil sie intern bereits Enum als Basisklasse<br />

besitzen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 207


Regeln und Hinweise<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 208


Regeln und Hinweise<br />

Wichtige Methoden und Operatoren einer Java-Klasse<br />

• Welche Methoden und Operatoren haben eine besondere Bedeutung (kleine Auswahl, hier<br />

anhand der Klasse Ghost)?<br />

Ghost()<br />

Methode/Operator<br />

protected void finalize()<br />

public boolean<br />

equals(Object s)<br />

public String toString()<br />

Bedeutung<br />

Standardkonstruktor. Wird immer dann automatisch<br />

erzeugt, wenn kein eigener Konstruktor geschrieben<br />

wurde.<br />

Wird aufgerufen, bevor das Objekt gelöscht wird.<br />

Kommt noch…<br />

Wird aufgerufen, wenn eine String-Darstellung des<br />

Objektes benötigt wird.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 209


Regeln und Hinweise<br />

Wichtige Methoden und Operatoren einer Java-Klasse<br />

• Identität und Gleichheit zweier Objekte (hier anhand der Klasse Ghost):<br />

Methode/Operator<br />

Ghost gh1 = new Ghost();<br />

Ghost gh2 = new Ghost ();<br />

if (gh1.equals(gh2))<br />

Ghost gh1 = new Ghost ();<br />

Ghost gh2 = new Ghost ();<br />

if (gh1 == gh2)<br />

Bedeutung<br />

Inhaltlicher Vergleich der Objekte. Dazu sollte<br />

die Methode equals der Klasse Ghost<br />

überschrieben werden.<br />

Identität der Objekte. Dazu werden die<br />

Referenzen auf die Objekte verglichen. Sind<br />

diese identisch, so handelt es sich um dasselbe<br />

Objekt.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 210


Regeln und Hinweise<br />

Wichtige Methoden und Operatoren – Vergleich von Objekten<br />

• Bedingungen für die Gleichheit zweier Objekte:<br />

Die Gleichheitsprüfung ist reflexiv: A ist gleich A.<br />

Die Gleichheitsprüfung ist symmetrisch: A ist gleich B ==> B ist gleich A.<br />

Die Gleichheitsprüfung ist transitiv: A ist gleich B und B ist gleich C ==> A ist gleich C.<br />

• Jede Implementierung muss diese Bedingungen einhalten!<br />

• Problem: Wie sieht der Vergleich bei Vererbung aus?<br />

-xPos: int<br />

-yPos: int<br />

Figure<br />

Die equals-Methode vergleicht<br />

die Positionen der Figuren<br />

+equals(o: Object): boolean<br />

Ghost<br />

-dangerous: boolean<br />

+equals(o: Object): boolean<br />

Die equals-Methode vergleicht<br />

die Positionen und die<br />

Gefährlichkeit der Geister<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 211


Regeln und Hinweise<br />

Wichtige Methoden und Operatoren – Vergleich von Objekten<br />

• Ohne Beweis: Der Vergleich von Objekten unterschiedlicher Klassen führt zur Verletzung<br />

mindestens einer Regeln.<br />

• Konsequenz: Nur Objekte identischer Klassen werden überhaupt auf Gleichheit überprüft.<br />

• Beispiel:<br />

public class Figure {<br />

private int xPos;<br />

private int yPos;<br />

// ...<br />

@Override<br />

public boolean equals(Object o) {<br />

if (o != null &&<br />

o.getClass() == getClass()) {<br />

Figure f = (Figure) o;<br />

return xPos == f.xPos<br />

&& yPos == f.yPos;<br />

}<br />

return false;<br />

}<br />

}<br />

public class Ghost extends Figure {<br />

private boolean dangerous;<br />

// ...<br />

@Override<br />

public boolean equals(Object o) {<br />

return super.equals(o) &&<br />

((Ghost) o).dangerous == dangerous;<br />

}<br />

}<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 212


Regeln und Hinweise<br />

Wichtige Methoden und Operatoren – Vergleich von Objekten<br />

• Erklärung des Beispiels:<br />

<br />

<br />

<br />

Die Basisklasse Figure testet mit getClass() zunächst auf identische Klassen.<br />

Nur dann werden die Attribute vergleichen.<br />

Die abgeleitete Klasse Ghost lässt die Basisklasse die Gleichheit feststellen und prüft<br />

dann das zusätzliche Attribut.<br />

• Anmerkung:<br />

<br />

<br />

In der Praxis ist es manchmal auch sinnvoll, nur die Basisklasse ohne Test auf<br />

Klassengleichheit die Prüfung vornehmen zu lassen hängt von der Aufgabe ab.<br />

Dann können eine Figur und ein Geist gleich sein!<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 213


Regeln und Hinweise<br />

Probleme bei Vererbung – Instabile Basisklasse<br />

• Und noch etwas gibt es bei Vererbung zu beachten, Beispiel:<br />

<br />

<br />

<br />

Die Klasse LoggingVector erbt von der Basisklasse Vector (Vererbung der<br />

Implementierung).<br />

LoggingVector protokolliert zusätzlich alle Aktionen von Vector.<br />

Die Methode clear wird nicht überschrieben, weil sie intern setValue aufruft.<br />

Vector<br />

E: class<br />

-values: E[*]<br />

+Vector(size: int)<br />

+setValue(index: int, value: E)<br />

+getValue(index: int): E<br />

+clear()<br />

public void clear() {<br />

for (int i = 0; i < values.length; i++)<br />

setValue(null, i);<br />

}<br />

LoggingVector<br />

+LoggingVector(size: int)<br />

+setValue(index: int: value: E)<br />

+getValue(index: int): E<br />

E: class<br />

setValue und getValue protokollieren die<br />

Aktion und rufen die Methoden der<br />

Basisklasse auf.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 214


Regeln und Hinweise<br />

Probleme bei Vererbung – Instabile Basisklasse<br />

• Wo ist jetzt das Problem?<br />

• Eine Änderung an der Basisklasse führt dazu, dass die abgeleitete Klasse nicht mehr korrekt<br />

funktioniert.<br />

-values: E[*]<br />

Vector<br />

+Vector(size: int)<br />

+setValue(index: int, value: E)<br />

+getValue(index: int): E<br />

+clear()<br />

kein Aufruf<br />

E: class<br />

Kein Aufruf von setValue mehr<br />

public void clear() {<br />

for (int i = 0; i < values.length; i++)<br />

values[ i ] = null;<br />

}<br />

LoggingVector<br />

+LoggingVector(size: int)<br />

+setValue(index: int, value: E)<br />

+getValue(index: int): E<br />

E: class<br />

setValue und getValue protokollieren die<br />

Aktion und rufen die Methoden der<br />

Basisklasse auf.<br />

• Beim Aufruf von clear erfolgt kein Logging mehr!<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 215


Regeln und Hinweise<br />

Probleme bei Vererbung – Instabile Basisklasse<br />

• Problem der instabilen Basisklassen (Fragile Base Class Problem):<br />

Anpassungen an einer Basisklasse führen zu unerwartetem Verhalten von abgeleiteten<br />

Klassen.<br />

Konsequenz: Anpassungen an Basisklassen können häufig nicht vorgenommen werden,<br />

ohne den Kontext der abgeleiteten Klassen mit einzubeziehen.<br />

Problem: Die Wartung objektorientierter Systeme, die häufig die Vererbung der<br />

Implementierung nutzen, wird stark erschwert.<br />

Konsequenz: Vererbung der Implementierung darf nicht eingesetzt wird, wenn spätere<br />

Änderungen an den Basisklassen wahrscheinlich sind.<br />

Ziel: Reine Vererbung der Spezifikation. Die Vermeidung von Redundanzen, kann auch<br />

über Delegationsbeziehungen erreicht werden.<br />

• Anmerkung: Wenn die abgeleitete Klasse sich exakt an die Spezifikation der Basisklasse hält<br />

und die Spezifikation später auch nicht verändert wird, ist das Erben einer Implementierung<br />

problemlos möglich.<br />

• In der Praxis: Niemand spezifiziert das Verhalten exakt…<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 216


Regeln und Hinweise<br />

Probleme bei Vererbung – Instabile Basisklasse<br />

• Lösung mit Delegation:<br />

<br />

VectorInterface<br />

E: class<br />

+setValue(index: int, value: T)<br />

+getValue(): E<br />

+clear()<br />

-values: E[*]<br />

-size: int<br />

Vector<br />

+Vector(size: int)<br />

+setValue(index: int, value: E)<br />

+getValue(index: int): E<br />

+clear()<br />

E: class E: class<br />

LoggingVector<br />

+LoggingVector(size: int)<br />

+setValue(index: int, value: E)<br />

+getValue(index: int): E<br />

+clear()<br />

LoggingVector delegiert die<br />

Aufrufe an Vector weiter,<br />

nachdem die Log-Ausgaben<br />

erfolgt sind.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 217


Regeln und Hinweise<br />

Probleme bei Vererbung – Instabile Basisklasse<br />

• Unvollständige Implementierung des Beispiels:<br />

public class LoggingVector implements VectorInterface {<br />

private Vector vector;<br />

}<br />

public LoggingVector(int size) {<br />

vector = new Vector(size);<br />

}<br />

@Override<br />

public void setValue(int index, E value) {<br />

// Log-Ausgaben, z.B. hier vereinfacht auf dem Bildschirm<br />

System.out.println("Neuer Wert " + value + " an Position " + index + " im Vektor");<br />

vector.setValue(value, index);<br />

}<br />

// usw.<br />

• Änderungen an der Implementierung von Vector beeinflussen nicht die Funktionsfähigkeit<br />

von LoggingVector.<br />

• Neue Methoden im Vector müssen auch in der Schnittstelle deklariert werden können so<br />

nicht in LoggingVector vergessen werden.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 218


Regeln und Hinweise<br />

Probleme bei Vererbung – Instabile Basisklasse<br />

• Fazit:<br />

<br />

<br />

<br />

Vererbung der Spezifikation ist sicherer in Bezug auf Änderungen.<br />

Vererbung der Implementierung erfordert häufig weniger Code teilweise aber<br />

automatisch generierbar (z.B. in Eclipse).<br />

Wenn sich Vererbung der Spezifikation leicht umsetzen lässt, ist diese Form der<br />

Vererbung vorzuziehen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 219


Klassendiagramme<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 220


Klassendiagramme<br />

Übersicht<br />

Einführung in Java und UML<br />

Arbeitsschritte und Software<br />

Imperative Aspekte<br />

Objektorientierte Programmierung<br />

Referenzen und dynamische<br />

Speicherverwaltung<br />

Vererbung<br />

Generische Klassen und Methoden<br />

Aufzähltypen<br />

Regeln und Hinweise<br />

Klassendiagramme<br />

Fehlerbehandlung mit Ausnahmen<br />

Pakete<br />

Annotationen<br />

Laufzeit-Typinformationen<br />

Ein- und Ausgabe<br />

Grafische Oberflächen und<br />

Animationen mit JavaFX<br />

Datenstrukturen<br />

Objektorientierter Entwurf<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 221


Klassendiagramme<br />

Modellierungswerkzeuge<br />

Leicht verfügbare Modellierungswerkzeuge<br />

• Visual Paradigm for UML<br />

<br />

<br />

<br />

• UML Lab<br />

<br />

<br />

Frei verfügbare Community-Edition, Lizenz für die Professional-Edition im Ilias<br />

http://www.visual-paradigm.com/<br />

keine Code-Erzeugung in der Community-Edition<br />

Lizenz für die Academic-Edition im Ilias<br />

http://www.uml-lab.com/de/download/<br />

• ArgoUML<br />

Open Source, nur UML 1.4<br />

<br />

<br />

<br />

http://argouml.tigris.org/<br />

Start ohne lokale Installation:<br />

http://argouml-downloads.tigris.org/jws/argouml-latest-stable.jnlp<br />

Code-Erzeugung für Java, C++, PHP, …<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 222


Klassendiagramme<br />

Modellierungswerkzeuge<br />

• Magicdraw<br />

<br />

<br />

<br />

• eUML<br />

<br />

<br />

<br />

Frei verfügbare Community-Edition<br />

http://www.magicdraw.com/<br />

Code-Erzeugung für C++, C# und Java (nicht Community-Edition)<br />

Auch als Open Source verfügbar, Eclipse-Plugin<br />

http://www.soyatec.com/euml2/installation/<br />

Code-Erzeugung nur für Java<br />

• Borland Together<br />

<br />

http://www.borland.com/us/products/together/index.html<br />

Lizenz bei Frau Knodel in LI 136<br />

• Fujaba<br />

<br />

<br />

<br />

Open Source<br />

http://www.fujaba.de/<br />

Code-Erzeugung nur für Java<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 223


Klassendiagramme<br />

Beziehungen zwischen Klassen<br />

Rückblick: Die UML-Darstellung einer Klasse<br />

-number: int<br />

-balance: int<br />

-count: int<br />

Account<br />

+payOff(amount: int)<br />

+transfer(amount: int, number: int)<br />

+payIn(amount:int)<br />

Klassenname<br />

Attribute<br />

statisches Attribut<br />

Operationen<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 224


Klassendiagramme<br />

Beziehungen zwischen Klassen<br />

Definition: Stereotyp<br />

Durch einen Stereotypen wird der Zweck oder die Rolle einer Klasse beschrieben.<br />

Einige vordefinierte Stereotypen:<br />

• : Diese Klasse unterstützt zentrale und wichtige Klassen des Modells <br />

Hilfsklasse.<br />

• : Diese Klasse stellt einen Teil der zentralen Logik der Anwendung dar.<br />

• : eine Schnittstelle (siehe früheres Kapitel)<br />

• : Von dieser Klasse gibt es keine Instanzen. Sie stellt lediglich (statische)<br />

Hilfsmethoden und -attribute zur Verfügung.<br />

• : neuer Datentyp, der nur bestimmte Werte annehmen kann <br />

Aufzähltyp<br />

• Es dürfen auch eigenen Stereotypen erstellt werden.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 225


Klassendiagramme<br />

Beziehungen zwischen Klassen<br />

Rückblick: Die UML-Darstellung eines Aufzähltyps<br />

• Java-Spezialitäten wie die Initialisierung der Werte durch Konstruktoren sind nicht<br />

vorgesehen.<br />

<br />

Direction<br />

NONE<br />

UP<br />

DOWN<br />

LEFT<br />

RIGHT<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 226


Klassendiagramme<br />

Beziehungen zwischen Klassen: Geschachtelte Klassen<br />

• Klassen dürfen in anderen Klassen deklariert werden.<br />

• Die Schachtelung<br />

<br />

<br />

erlaubt es der inneren Klasse, auf die Daten der äußeren zuzugreifen und<br />

bietet die Möglichkeit, eine Klasse, die im Wesentlichen nur von einer anderen<br />

verwendet wird, auch in dieser zu deklarieren.<br />

Aussen<br />

<br />

Innen<br />

-attribut: int<br />

public class Aussen {<br />

class Innen {<br />

int attribut;<br />

// ...<br />

}<br />

// ...<br />

}<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 227


Klassendiagramme<br />

Beziehungen zwischen Klassen<br />

• Zwischen Klassen können unterschiedliche Beziehungen bestehen.<br />

• Die Beziehungen lassen sich ja nach Aufgabe in unterschiedliche Kategorien einteilen.<br />

Kategorien in der UML:<br />

• Assoziation<br />

• Aggregation und Komposition („Teil und Ganzes“)<br />

• Vererbung (von einer Spezifikation, von einer Implementierung)<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 228


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

Definition: Binäre Assoziation<br />

Eine binäre Assoziation beschreibt die semantische Beziehung zwischen zwei Klassen.<br />

Beispiel:<br />

GameController<br />

Pacman<br />

Assoziation<br />

• Pacman und GameController „kennen“ sich.<br />

• Beide Klassen können auf der jeweils anderen Operationen aufrufen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 229


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Leserichtung (GameController steuert Pacman):<br />

Name der Assoziation<br />

GameController<br />

steuert<br />

Pacman<br />

Leserichtung<br />

• Multiplizität (wie viele Objekte können gleichzeitig an der Beziehung beteiligt sein):<br />

max. Anzahl Controller im Spiel<br />

GameController<br />

1 steuert 1..*<br />

Figure<br />

Der Controller steuert mindestens einen, max. beliebig viele Figuren.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 230


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Rolle (sie beschreibt, welche Funktion/Rolle eine an einer Assoziation beteiligten Klasse<br />

einnimmt):<br />

Grosshaendler<br />

Haendler<br />

-verkaeufer<br />

-kaeufer<br />

-verkaeufer<br />

Sichtbarkeit<br />

der Rolle<br />

Name<br />

der Rolle<br />

-kaeufer<br />

Endkunde<br />

<br />

Zweck einer Rolle:<br />

- Besseres Verständnis der Assoziation<br />

- Name des Attributs in der Implementierung<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 231


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Implementierungsbeispiel, in dem der Name der Rolle den Namen des Attributes ergibt:<br />

public class Haendler {<br />

private ArrayList verkaeufer;<br />

private ArrayList kaeufer;<br />

}<br />

// Methoden usw.<br />

• Im Falle einer automatischen Code-Erzeugung ergeben sich so lesbare Attributnamen im<br />

Quelltext.<br />

• Achtung: Eine Rolle mit privater Sichtbarkeit kann durch Getter- und Setter-Methoden von<br />

„außen“ zugänglich gemacht werden.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 232


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Eigenschaft (ähnlich wie Eigenschaften von Attributen geben sie Eigenschaften von<br />

Assoziationen nähere Hinweise auf die Umsetzung der Assoziation):<br />

GameController<br />

{ordered}<br />

bearbeitet<br />

Figure<br />

<br />

Eigenschaft<br />

Der Controller benötigt die Figuren in einer bestimmten Reihenfolge (ist in der<br />

Beispielimplementierung aber nicht der Fall).<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 233


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

<br />

Eigenschaftstypen (unvollständig):<br />

- {subsets }: Die Menge der Objekte an diesem<br />

Assoziationsende ist eine Teilmenge der Objekte am Assoziationsende<br />

.<br />

- {union}: Die Menge der Objekte an diesem Assoziationsende ist die Vereinigung<br />

aller seiner subsets-Assoziationsenden.<br />

Beispiel (die Buchbestellung setzt sich aus den bereits gelieferten und den nicht<br />

verfügbaren Büchern zusammen):<br />

Bestellung<br />

geliefert<br />

{subsets bestellt}<br />

Buch<br />

nicht_vorhanden<br />

{subsets bestellt}<br />

/bestellt<br />

{union}<br />

Die Menge bestellt ist aus allen<br />

Teilmengen abgeleitet. Es kommen<br />

keine weiteren Bücher hinzu.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 234


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

- {ordered}: Die so markierten Objekte am Ende der Assoziation liegen sortiert vor.<br />

Duplikate sind nicht erlaubt.<br />

- {bag}: Dasselbe Objekt darf am Ende der Assoziation mehrfach erscheinen.<br />

- {seq} bzw. {sequence}: Das Ende der Assoziation verweist auf eine geordnete<br />

Menge von Objekten. Duplikate sind erlaubt.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 235


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Einschränkung (Teilnahme eines Objektes an einer Assoziation angeben).<br />

<br />

<br />

Einschränkungstypen:<br />

- {or}: Das Objekt muss eine der beiden Assoziationen verwenden.<br />

- {xor}: Das Objekt darf nur eine der beiden Assoziationen verwenden.<br />

- {and}: Das Objekt muss an beiden Assoziationen teilnehmen lässt sich besser<br />

durch Kardinalität 1 ausdrücken.<br />

Beispiel für ein Meilenkonto bei einer Fluggesellschaft:<br />

Meilenkonto<br />

inhaber<br />

Firma<br />

xor<br />

EMail<br />

Ein Meilenkonto<br />

gehört entweder<br />

einer Firma oder<br />

einer Person.<br />

inhaber<br />

Person<br />

or<br />

Anschrift<br />

Eine Person muss<br />

eine EMail-Adresse<br />

oder eine Anschrift<br />

angeben.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 236


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

<br />

Implementierung einer xor-Einschränkung:<br />

- Programmgesteuert überprüfen<br />

- Durch Vererbung und Einführung einer weiteren Klasse:<br />

Meilenkonto<br />

xor<br />

inhaber<br />

Firma<br />

Person<br />

inhaber<br />

Person<br />

Meilenkonto<br />

inhaber<br />

1<br />

JuristischePerson<br />

Firma<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 237


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Navigierbarkeit (erlaubt die Angabe, in welche Richtung eine Assoziation gelesen wird). Es<br />

werden folgende Arten unterstützt:<br />

<br />

Navigierbar: Die Klasse Field kennt die Klasse Pacman am Ende der Assoziation.<br />

Field<br />

Pacman<br />

<br />

Nicht navigierbar: Die Klasse Pacman kennt die Klasse Ghost am Ende der Assoziation<br />

nicht.<br />

Pacman<br />

Ghost<br />

<br />

Unspezifiziert: Es wird keine Aussage über die Navigierbarkeit getroffen. In der Praxis<br />

wird das häufig als navigierbar interpretiert.<br />

GameController<br />

Pacman<br />

<br />

Bidirektionale Navigierbarkeit: Beide Klassen kennen sich gegenseitig und können so<br />

auch jeweils die Methoden des Anderen aufrufen.<br />

GameController<br />

Pacman<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 238


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

<br />

<br />

Verbot der Navigierbarkeit: Beide Klasse dürfen sich nicht kennen. Es besteht zwar eine<br />

logische Beziehung, die aber nicht durch eine Assoziation ausgedrückt werden soll <br />

nicht sehr gebräuchlich.<br />

Ghost<br />

Pacman<br />

Unidirektionale Navigierbarkeit: Die Navigation ist in nur einer Richtung erlaubt.<br />

Field<br />

Pacman<br />

<br />

Teilweise Spezifikation der Navigation: Es ist offen gelassen, ob Pacman auch das Field<br />

kennt.<br />

Field<br />

Pacman<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 239


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Implementierung einer Assoziation:<br />

GameController<br />

-controller -figures<br />

1 controls 1..*<br />

Figure<br />

public class GameController {<br />

private ArrayList figures;<br />

// ...<br />

}<br />

public abstract class Figure {<br />

private GameController controller;<br />

// ...<br />

}<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 240


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Reflexive Assoziation: Eine Assoziation einer Klasse zu sich selbst, ansonsten handelt es sich<br />

im eine normale Assoziation.<br />

Mitarbeiter<br />

-vorgesetzter<br />

0..1<br />

-untergebener<br />

*<br />

leitet<br />

<br />

<br />

<br />

Der Vorgesetzte hat mindestens einen Untergebenen.<br />

Jeder Untergebene hat maximal einen Vorgesetzten. Jeder Vorgesetzte kann also auch<br />

wieder Mitarbeiter sein.<br />

Implementierungsmöglichkeit:<br />

public class Mitarbeiter {<br />

private Mitarbeiter vorgesetzter;<br />

private ArrayList untergebener;<br />

}<br />

// ...<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 241


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

N-äre Assoziation<br />

Eine n-äre Assoziation ist die allgemeine Form einer Assoziation zwischen n Klassen.<br />

Vorspeise<br />

0..*<br />

Hauptgericht<br />

Dessert<br />

0..* 0..*<br />

Menue<br />

Assoziationsname<br />

• Erklärung des Beispiels:<br />

<br />

Die drei Klassen stehen in einer Beziehung namens Menue.<br />

Nicht jedes Hauptgericht muss in einem Menü vorkommen (Multiplizität 0).<br />

Jedes Hauptgericht kann in beliebig vielen Menüs vorkommen (Multiplizität *).<br />

<br />

Wenn ein Hauptgericht in mindestens einem Menü vorhanden sein muss, würde man<br />

am Hauptgericht die Multiplizität 1..* eintragen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 242


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Wie kann eine n-äre Assoziation implementiert werden?<br />

• Ganz einfach durch Umsetzung in mehrere binäre Assoziationen:<br />

Vorspeise<br />

0..*<br />

Hauptgericht<br />

0..* 0..*<br />

Menue<br />

Dessert<br />

Vorspeise<br />

1<br />

Hauptgericht<br />

1<br />

0..*<br />

Menue<br />

0..* 0..*<br />

1<br />

Dessert<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 243


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Qualifizierte Assoziation:<br />

Eine qualifizierte Assoziation besitzt einen Qualifizierer, der eine Menge von Attributen<br />

besitzt, die das Objekt am anderen Ende der Assoziation eindeutig referenziert.<br />

Eine qualifizierte Assoziation ist nur für binäre Assoziationen definiert.<br />

• Beispiel:<br />

<br />

<br />

Jeder Mitarbeiter in einer Firma wird über seine Personalausweisnummer eindeutig<br />

identifiziert. Nicht zu jeder Ausweisnummer gibt es einen Mitarbeiter (Multiplizität<br />

0..1).<br />

Ein Mitarbeiter darf für beliebig viele Firmen arbeiten, hat aber in jeder dieselbe<br />

Personalausweisnummer (Multiplizität 1..*).<br />

Firma<br />

persNummer<br />

Lohnzahlung<br />

1..* 0..1<br />

Mitarbeiter<br />

-persNummer: int<br />

Qualifizierer<br />

Qualifizierte<br />

Assoziation<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 244


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Vergleich zu einer normalen Assoziation:<br />

Firma<br />

Lohnzahlung<br />

1..* 1..*<br />

Mitarbeiter<br />

-persNummer: int<br />

n-zu-m-Beziehung<br />

Firma<br />

persNummer<br />

Lohnzahlung<br />

1..* 0..1<br />

Mitarbeiter<br />

-persNummer: int<br />

Die Beziehung zum Mitarbeiter wird genauer<br />

spezifiziert Fremdschlüsselkonzept in<br />

Datenbanken.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 245


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Implementierung einer qualifizierten Assoziation:<br />

public class Mitarbeiter {<br />

private int persNummer;<br />

}<br />

// ...<br />

// persNummer ist der Index im Vektor<br />

public class Firma {<br />

private ArrayList mitarbeiter;<br />

}<br />

// ...<br />

// persNummer ist der Schlüssel in<br />

// einer Hashtabelle oder einem Baum<br />

// (kommen noch...)<br />

public class Firma {<br />

private HashMap<br />

mitarbeiter;<br />

}<br />

// ...<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 246


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Assoziationsklasse: Eine Assoziationsklasse ist eine Assoziation, die neben Attributen auch<br />

Operationen wie bei einer Klasse aufnehmen kann:<br />

<br />

Die Namen der Assoziation und ihrer Klasse müssen identisch sein.<br />

Einsatz: Zusätzliche Attribute können logisch keinem der Enden der Assoziation<br />

zugeordnet werden Ablage in der Assoziationsklasse.<br />

• Beispiel: Die Auftragsnummer kann weder der Firma noch dem Kunden zugeordnet werden.<br />

Firma<br />

Auftrag<br />

1..* 1..*<br />

Kunde<br />

Auftrag<br />

-nummer: int<br />

Assoziationsklasse<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 247


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Implementierung: Weder C++ noch Java kennen Assoziationsklassen Einführung einer<br />

„Zwischenklasse“:<br />

Firma<br />

Auftrag<br />

1..* 1..*<br />

Kunde<br />

Auftrag<br />

-nummer: int<br />

Firma<br />

Auftrag<br />

fuehrtAus<br />

erteilt<br />

-nummer: int<br />

1 1..* 1..* 1<br />

Kunde<br />

• Der Kunde erteilt beliebig viele Aufträge.<br />

• Eine Firma kann beliebig viele Aufträge ausführen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 248


Klassendiagramme<br />

Beziehungen zwischen Klassen: Assoziation<br />

• Implementierung einer Assoziationsklasse:<br />

public class Auftrag {<br />

private int nummer;<br />

private Kunde kunde;<br />

private Firma firma;<br />

}<br />

// ...<br />

public class Firma {<br />

private ArrayList auftraege;<br />

}<br />

// ...<br />

public class Kunde {<br />

private ArrayList auftraege;<br />

}<br />

// ...<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 249


Klassendiagramme<br />

Beziehungen zwischen Klassen: Aggregation<br />

Definition: Aggregation<br />

Eine Aggregation ist eine spezielle Form einer binären Assoziation. Sie beschreibt eine Teil-<br />

Ganzes-Beziehung zwischen genau zwei Klassen.<br />

• Beispiel:<br />

Field<br />

Ganzes<br />

0..1<br />

0..*<br />

Figure<br />

Aggregation<br />

Teil<br />

Das Teil kennt das<br />

Ganze nicht (Pfeilspitze).<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 250


Klassendiagramme<br />

Beziehungen zwischen Klassen: Aggregation<br />

• Eigenschaften einer Aggregation:<br />

<br />

<br />

<br />

<br />

Die Lebensdauer des Ganzen ist von der Lebensdauer der Teile unabhängig.<br />

Die Lebensdauer der Teile ist von der Lebensdauer des Ganzen unabhängig.<br />

Teile können in mehreren Ganzen gleichzeitig verwendet werden.<br />

Die Teile kennen das Ganze häufig nicht.<br />

• Einsatzgebiete für Aggregation:<br />

<br />

<br />

<br />

Das Ganze handelt als Stellvertreter für seine Teile.<br />

Es nimmt Aufträge entgegen und delegiert diese an die Teile.<br />

Beispiel: Pacman<br />

- Ganzes: Spielfeld<br />

- Teile: Einzelne Figuren in der Zeichenfläche<br />

- Auftrag: Anforderung, sich neu zu zeichnen<br />

- Delegation: Jedes Teil erhält den Auftrag, sich selbst neu zu zeichnen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 251


Klassendiagramme<br />

Beziehungen zwischen Klassen: Aggregation<br />

• Implementierung einer Aggregation:<br />

public class Field {<br />

private ArrayList figures;<br />

public abstract class Figure {<br />

}<br />

// ...<br />

}<br />

// ...<br />

• Hinweise:<br />

<br />

<br />

Das Ganze erzeugt und löscht die Teile i.d.R. nicht selbst.<br />

Das Ganze besitzt häufig Methoden zum Hinzufügen und Entfernen von Teilen sowie<br />

zum Besuchen aller Teile.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 252


Klassendiagramme<br />

Beziehungen zwischen Klassen: Komposition<br />

Definition: Komposition<br />

Eine Komposition ist eine starke Form der Aggregation. Hier sind das Ganze und seine Teile<br />

untrennbar miteinander verbunden.<br />

• Beispiel:<br />

GameController<br />

Ganzes<br />

Komposition, Multiplizität ist 1<br />

0..*<br />

Figure<br />

Das Teil kennt das<br />

Ganze nicht (Pfeilspitze).<br />

Teil<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 253


Klassendiagramme<br />

Beziehungen zwischen Klassen: Komposition<br />

• Eigenschaften einer Komposition:<br />

Die Lebensdauer des Ganzen ist von der Lebensdauer der Teile unabhängig. Beim<br />

Löschen eines Teils bleibt das Ganze bestehen.<br />

Die Lebensdauer der Teile ist von der Lebensdauer des ganzen abhängig: Beim Löschen<br />

des Ganzen werden die Teile auch gelöscht.<br />

Teile können nicht in mehreren Ganzen gleichzeitig verwendet werden.<br />

Die Teile kennen das Ganze häufig nicht.<br />

• Einsatzgebiete für Komposition siehe Aggregation<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 254


Klassendiagramme<br />

Beziehungen zwischen Klassen: Komposition<br />

• Spezialfall der Komposition: Multiplizität 0..1<br />

GameController<br />

0..*<br />

Figure<br />

0..1<br />

• Figuren dürfen außerhalb und ohne Bezug zum Controller erzeugt werden.<br />

• Sie werden dann als Teile am Controller registriert und gehören ab diesem Zeitpunkt zum<br />

Controller.<br />

• Figuren dürften auch an einen anderen Controller übertragen werden.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 255


Klassendiagramme<br />

Beziehungen zwischen Klassen: Komposition<br />

• Implementierung einer Komposition (in Java wie bei einer Aggregation):<br />

public class GameController {<br />

private ArrayList figures;<br />

public abstract class Figure {<br />

}<br />

// ...<br />

}<br />

// ...<br />

• Hinweise:<br />

<br />

<br />

Häufig ist es sinnvoll, dass das Ganze die Teile selbst erzeugt und löscht: Die Teile können<br />

nicht so versehentlich auch ohne das Ganze verwendet werden.<br />

Das Ganze besitzt i.d.R. Methoden zum Erzeugen und Entfernen von Teilen sowie zum<br />

Besuchen aller Teile.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 256


Klassendiagramme<br />

Beziehungen zwischen Klassen: Hinweise zur Auswahl<br />

• Wann wird ein bestimmter Beziehungstyp verwendet?<br />

<br />

<br />

<br />

<br />

Existenzabhängige Teil-Ganzes-Beziehung: Komposition<br />

Logische Einheit, die nicht existenzabhängig ist: Aggregation<br />

Kaskadierende Methodenaufrufe: Aggregation (z.B. Pacman-Spiel, in dem die Spielfläche<br />

die Aufrufe zum Neuzeichnen an die Figuren weiter leitet)<br />

Rumbaugh: „Think of Aggregation as a modeling placebo“.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 257


Klassendiagramme<br />

Beziehungen zwischen Klassen: Abhängigkeit<br />

Definition: Abhängigkeit<br />

Eine Abhängigkeit zeigt, dass eine Klasse (Client) eine andere (Supplier) zur Erfüllung ihrer<br />

Aufgaben benötigt. Die Abhängigkeit dient nur der Dokumentation.<br />

• Beispiel (Bewerber ruft eine Methode der Klasse Firma auf):<br />

Firma<br />

+bewerben()<br />

<br />

Bewerber<br />

+bewerben()<br />

Supplier<br />

Client<br />

• Implementierung:<br />

public class Bewerber {<br />

}<br />

public void bewerben(Firma firma) {<br />

firma.bewerben(this);<br />

}<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 258


Klassendiagramme<br />

Beziehungen zwischen Klassen: Abhängigkeit<br />

• Abhängigkeitstypen werden durch sogenannte Stereotypen beschrieben. Vordefiniert sind<br />

(unvollständig):<br />

: Der Client ruft mindestens eine Methode des Suppliers auf.<br />

: Der Client erzeugt Supplier-Objekte.<br />

: Der Client ist logisch aus dem Supplier abgeleitet. Er kann beispielsweise<br />

dieselbe Funktionalität wie der Supplier erfüllen, wurde aber aus<br />

Geschwindigkeitsgründen anders implementiert.<br />

: Der Supplier gewährt dem Client Zugriff auf private Daten.<br />

: Der Client kann den Supplier (ohne dass es eine Vererbung zwischen<br />

ihnen gibt) direkt ersetzen.<br />

: Der Client benötigt den Supplier für seine Funktion.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 259


Klassendiagramme<br />

Beziehungen zwischen Klassen: Vererbung von einer Implementierung<br />

Definition: Vererbung von einer Implementierung (Generalisierung)<br />

Die Vererbung beschreibt eine Beziehung zwischen einer Basisklasse und einer abgeleiteten<br />

Klasse. Details: Siehe vorherige Kapitel<br />

• Beispiel:<br />

Figure<br />

passive Figur<br />

passive Figur<br />

steuerbare Figur<br />

Diskriminator<br />

(optional)<br />

Ghost Cherry Pacman<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 260


Klassendiagramme<br />

Beziehungen zwischen Klassen: Vererbung von einer Implementierung<br />

• Der Diskriminator kann bei Gleichheit auch so notiert werden:<br />

gilt für beide<br />

Klassen<br />

Figure<br />

passive Figur<br />

steuerbare Figur<br />

Ghost Cherry Pacman<br />

• Durch den Diskriminator können<br />

<br />

<br />

Gruppen zusammengehöriger Klassen erkannt werden<br />

weitere Eigenschaften einer Vererbung gegeben werden.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 261


Klassendiagramme<br />

Beziehungen zwischen Klassen: Vererbung von einer Implementierung<br />

• Eigenschaften von Diskriminatoren:<br />

<br />

{complete, disjoint}: Die Klassen an dem Diskriminator sind vollständig. Sie<br />

decken alle möglichen Objekte ab (complete). Ein Objekt kann nicht gleichzeitig<br />

Pacman und Geist sein (disjoint).<br />

Eigenschaft<br />

Figure<br />

{complete, disjoint}<br />

Typ<br />

Ghost Cherry Pacman<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 262


Klassendiagramme<br />

Beziehungen zwischen Klassen: Vererbung von einer Implementierung<br />

<br />

{incomplete, disjoint}: Die Gruppe des Diskriminators ist unvollständig<br />

(incomplete), da beispielsweise die Kirschen fehlen. Ein Pacman kann nicht gleichzeitig<br />

Geist sein (disjoint).<br />

Figure<br />

{incomplete, disjoint}<br />

Typ<br />

Ghost<br />

Pacman<br />

<br />

Ohne Angabe wird {disjoint} angenommen.<br />

• Die Vererbung von einer abstrakten Basisklasse und einer nicht-abstrakten Basisklasse erfolgt<br />

genau gleich.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 263


Klassendiagramme<br />

Beziehungen zwischen Klassen: Mehrfachvererbung<br />

• Mehrfachvererbung einer Implementierung: Eine Klasse hat mehr als eine direkte Basisklasse<br />

(in Java nicht möglich).<br />

HSAngehoeriger<br />

{incomplete, overlapping}<br />

Student<br />

Taetigkeit<br />

Dozent<br />

Tutor<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 264


Klassendiagramme<br />

Beziehungen zwischen Klassen: Mehrfachvererbung<br />

• Diskriminatoren (Fortsetzung):<br />

<br />

<br />

{incomplete, overlapping}: Die Gruppe des Diskriminators ist unvollständig<br />

(incomplete). Ein Objekt kann Instanz von mehr als einer Basisklasse sein<br />

(overlapping).<br />

{complete, overlapping}: Die Gruppe des Diskriminators ist vollständig<br />

(complete). Ein Objekt kann Instanz von mehr als einer Basisklasse sein<br />

(overlapping).<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 265


Klassendiagramme<br />

Beziehungen zwischen Klassen: Vererbung von einer Spezifikation<br />

Definition: Vererbung von einer Spezifikation<br />

Diese Art der Vererbung beschreibt die Implementierung einer Schnittstelle. Details: Siehe<br />

vorherige Kapitel<br />

• Beispiel:<br />

<br />

Comparable<br />

T: class<br />

+compareTo(o: T): int<br />

Schnittstellenimplementierung<br />

String<br />

Integer<br />

+compareTo(o: String): int<br />

+compareTo(o: Integer): int<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 266


Klassendiagramme<br />

Beziehungen zwischen Klassen: Vererbung von einer Spezifikation<br />

• Alternative Darstellung mit Ball-Symbol (die Klasse String implementiert die Schnittstelle<br />

Comparable):<br />

String<br />

implementierte<br />

Schnittstelle<br />

+compareTo(o: String): int<br />

Comparable<br />

Schnittstellenname<br />

• Algorithmen und Datenstrukturen operieren häufig nur auf Schnittstellen:<br />

<br />

<br />

Klassendiagramme einer Beziehung genau wie bei einer Abhängigkeit zwischen Klassen<br />

notwendig<br />

Hier: Klasse benötigt eine Schnittstelle<br />

SortedContainer<br />

<br />

<br />

Comparable<br />

T: class<br />

benötigte<br />

Schnittstelle<br />

+compareTo(o: T): int<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 267


Klassendiagramme<br />

Beziehungen zwischen Klassen: Vererbung von einer Spezifikation<br />

• Alternative Darstellung mit dem Ball-Symbol:<br />

SortedContainer<br />

benötigte<br />

Schnittstelle<br />

Comparable<br />

Schnittstellenname<br />

• Gemeinsame Darstellung: Schnittstelle, implementierende Klasse und Klasse, die die<br />

Schnittstelle benötigt, in der Ball-Darstellung:<br />

SortedContainer<br />

String<br />

Comparable<br />

+compareTo(o: String): int<br />

• Implementierung:<br />

public class SortedContainer {<br />

private Comparable[] elements;<br />

// ...<br />

}<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 268


Klassendiagramme<br />

Beziehungen zwischen Klassen: Generische Klassen<br />

• Zwischen generischen und konkreten Klassen als Instanzen der generischen Klassen<br />

existieren auch Beziehungen.<br />

• Erinnerung: Generische Klasse in UML<br />

Vector<br />

E: class<br />

-values: E[*] {bag}<br />

+Vector(size: int, initValue: E)<br />

+setValue(index: int, E: value)<br />

+getValue(index: int): E<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 269


Klassendiagramme<br />

Beziehungen zwischen Klassen: Vererbung einer Assoziation<br />

• Die Vererbung von Assoziationen wird meist in folgenden Szenarien verwendet:<br />

<br />

Es besteht bereits eine Assoziation zwischen zwei Basisklassen.<br />

Es soll ausgedrückt werden, dass die Assoziation einer abgeleiteten Klasse immer nur mit<br />

der Assoziation einer anderen abgeleiteten Klasse hergestellt werden soll.<br />

• Beispiel:<br />

Artikel<br />

*<br />

schreibt<br />

1<br />

Person<br />

Fachartikel<br />

-artikel<br />

-autor<br />

Redakteur<br />

Nur der Redakteur<br />

kann Fachartikel<br />

schreiben Eine<br />

Assoziation kann<br />

z.B. nicht von einer<br />

„normalen“ Person<br />

zum Fachartikel führen.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 270


Klassendiagramme<br />

Anmerkungen im Klassendiagramm<br />

Definition: Anmerkung<br />

Eine Anmerkung beinhaltet einen Kommentar für ein beliebiges UML-Sprachelement.<br />

• Beispiel:<br />

Die Figur ist das zentrale<br />

Element in einer<br />

Zeichenfläche.<br />

+paint()<br />

Figure<br />

Zuordnung<br />

Anmerkung<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 271


Klassendiagramme<br />

Übersicht zu Klassendiagramm (vereinfacht)<br />

Darstellung der wichtigsten Elemente durch MagicDraw:<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 272


Klassendiagramme<br />

Klassen im Pacman-Spiel (unvollständig)<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 273


Klassendiagramme<br />

Beispiel aus der Klausur WS 2012/2013<br />

• Fiktives Flugbuchungssystem:<br />

<br />

<br />

<br />

<br />

<br />

Kunde: Name, Anschrift, E-Mail-Adresse, Angabe (privat/geschäftlich), Login-Name,<br />

Passwort<br />

Flug: Flugnummer, Datum, Uhrzeit, Start- und Endflughafen, Gebühr, abhängig vom<br />

Startflughafen, Preis, abhängig von der Klasse (1. Klasse, Business-Klasse, 2. Klasse). Es<br />

werden alle Sitze einer Klasse zum selben Preis angeboten.<br />

Buchung: Jeder Kunde kann beliebig viele Flugbuchungen gleichzeitig vornehmen. Eine<br />

Buchung kann mehrere Sitzplätze in derselben Klasse umfassen. Die Zahlungsart müssen<br />

Sie nicht berücksichtigen.<br />

Reservierung: Ist sich ein Kunde noch nicht ganz sicher, ob er einen Flug buchen möchte,<br />

dann kann er sich diesen für einen Zeitraum von 24 Stunden kostenlos reservieren.<br />

Zusatzoptionen bei der Buchung: Zu einem Flug können optionale Leistungen<br />

hinzugebucht werden, für die aber zusätzliche Kosten anfallen<br />

(Reiserücktrittsversicherung, Sitzplatz am Notausstieg, Übergepäck, eventuell weitere (je<br />

nach Fluggesellschaft und Flugzeugtyp).<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 274


Fehlerbehandlung mit Ausnahmen<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 275


Fehlerbehandlung mit Ausnahmen<br />

Motivation<br />

• Welche Arten von Fehlern gibt es?<br />

• Wie können Laufzeitfehler sicher gefunden werden?<br />

• Wie sollten Laufzeitfehler einer Methode dem Aufrufer mitgeteilt werden?<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 276


Fehlerbehandlung mit Ausnahmen<br />

Fehlerklassifikation<br />

• Erwartete Fehler durch Aufruf einer prinzipiell unsicheren Methode<br />

<br />

<br />

<br />

<br />

Auftreten: Es muss bei jedem Aufruf mit dem Fehler gerechnet werden.<br />

Beispiel: Versuch, eine Datei zum Lesen zu öffnen, die nicht existiert<br />

Vermeidung: nicht möglich<br />

Behandlung: ja<br />

• Unerwartete Fehler durch Programmierfehler oder mangelnde Systemressourcen<br />

<br />

<br />

<br />

<br />

Auftreten: Eigentlich sollte der Fehler nie auftreten.<br />

Beispiel: zu wenig Hauptspeicher vorhanden, Stacküberlauf<br />

Vermeidung: nur begrenzt möglich (intensive Programmtests)<br />

Behandlung: nur begrenzt möglich (z.B. Datensicherung vor der Programmbeendigung)<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 277


Fehlerbehandlung mit Ausnahmen<br />

Fehlerklassifikation<br />

• Sonderfall: Erwarteter oder unerwarteter Fehler während der Fehlerbehandlung<br />

<br />

<br />

<br />

<br />

Auftreten: siehe erwarteter und unerwarteter Fehler<br />

Beispiel: Die Fehlermeldung kann wegen fehlender Schreibrechte oder zu geringen<br />

freien Hauptspeichers nicht in eine Datei geschrieben werden.<br />

Vermeidung: nur bei sehr einfacher Fehlerbehandlung möglich<br />

Behandlung: hängt vom Fehler ab<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 278


Fehlerbehandlung mit Ausnahmen<br />

Reaktionen auf Fehler<br />

• Sofort behandelbarer Fehler<br />

Auswirkung: Das Programm kann auf den Fehler reagieren und seine Arbeit (eventuell<br />

eingeschränkt) fortsetzen.<br />

Reaktion: ignorieren (wenn sinnvoll möglich), alternativen Programmablauf starten<br />

Beispiel: Bei fehlender Eingabedatei werden immer Standardwerte angenommen.<br />

• Nicht sofort behandelbarer Fehler<br />

Auswirkung: Der Fehler kann an der Stelle, an der er auftritt, nicht behandelt werden.<br />

Reaktion: Fehlermeldung an den Aufrufer der Methode<br />

Beispiel: Datei existiert nicht sollen Standardwerte verwendet werden/soll der<br />

Benutzer gefragt werden? Kann eventuell an der Stelle des Fehlers nicht entschieden<br />

werden.<br />

• Nicht sinnvoll behandelbarer Fehler<br />

Auswirkung: sinnvolle Programmfortsetzung nicht möglich<br />

Reaktion: i.d.R. Programmbeendigung mit vorheriger Datensicherung (sofern möglich)<br />

Beispiel: Stacküberlauf, schwere Programmierfehler<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 279


Fehlerbehandlung mit Ausnahmen<br />

Exceptions – Idee<br />

• Fehlerbehandlung bisher:<br />

<br />

<br />

<br />

Ein Methode m1 stellt einen Fehler fest und liefert ein Ergebnis, das diesen Fehler<br />

beschreibt.<br />

Die aufrufende Methode m1 der Methode m2 stellt fest, dass m2 einen Fehler<br />

zurückliefert und beendet die eigene Arbeit mit der Rückgabe eines Fehlers.<br />

usw...<br />

• Schlechte Lösung, da sich eventuell große Teile einer Methode mit der Fehlerbehandlung<br />

befassen. Eine Trennung von Fehler- und Normalfall ist nicht vorhanden.<br />

• Fehler werden häufig über viele Aufrufebenen hinweg nach „oben“ weitergereicht, ohne<br />

dass die Fehler direkt bearbeitet werden.<br />

• Java bietet das Konzept der Ausnahme (Exception) zur besseren Fehlerbehandlung. Damit<br />

muss nicht der Rückgabewert einer Methode zur Fehlerübermittlung missbraucht werden.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 280


Fehlerbehandlung mit Ausnahmen<br />

Exceptions – Idee<br />

Einsatzgebiete<br />

• Meldung von Fehlern, die nicht lokal am Ort der Entstehung behoben werden konnten:<br />

Beispielsweise kann der Autor einer Bibliothek Laufzeitfehler („Datei existiert nicht“ etc.)<br />

zwar erkennen, er ist aber selten in der Lage, diese im Kontext des aufrufenden<br />

Programms richtig zu behandeln.<br />

Der Anwender der Bibliothek dagegen weiß, wie er mit den Fehlern umgehen soll.<br />

• Die Behandlung von anderswo gefundenen Fehlern.<br />

• Syntax:<br />

try {<br />

// versuche, eine Aufgabe zu lösen<br />

}<br />

catch (Fehlerklasse fehler) {<br />

// behandle Fehler des Typs "Fehlerklasse"<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 281


Fehlerbehandlung mit Ausnahmen<br />

Exceptions – Idee<br />

• Beispiel (Zugriff auf den Vektor, angelehnt an ArrayList):<br />

public class Vector {<br />

private E[] values;<br />

private int size;<br />

// ...<br />

public E getValue(int index) {<br />

if (index >= size || index < 0)<br />

throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);<br />

return values[ index ];<br />

}<br />

}<br />

public static void main(String[] args) {<br />

Vector vector = new Vector(3, 0.0);<br />

try {<br />

System.out.println(vector.getValue(0));<br />

System.out.println(vector.getValue(4));<br />

}<br />

catch (IndexOutOfBoundsException ex) {<br />

System.err.println("Oops" + ex.getMessage());<br />

}<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 282


Fehlerbehandlung mit Ausnahmen<br />

Mehrere Exceptions<br />

Behandlung mehrerer Ausnahmen<br />

• Syntax:<br />

try {<br />

// versuche, eine Aufgabe zu lösen<br />

}<br />

catch (FehlerTyp1 ex1) {<br />

// behandle Fehler-Typ1<br />

}<br />

catch (FehlerTyp2 ex2) {<br />

// behandle Fehler-Typ2<br />

}<br />

• Unbehandelte Ausnahmen:<br />

Beendigung der Methode<br />

Auslösung der Ausnahme in der aufrufenden Methode<br />

Dieses Spiel funktioniert solange, bis eine Methode die Ausnahme abfängt oder das<br />

Programm beendet wurde.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 283


Fehlerbehandlung mit Ausnahmen<br />

Mehrere Exceptions<br />

• Es dürfen auch mehrere, unabhängige Fehler durch ein sogenanntes „multi-catch“<br />

abgefangen werden:<br />

• Syntax:<br />

try {<br />

// versuche, eine Aufgabe zu lösen<br />

}<br />

catch (FehlerTyp1 ex1 | FehlerTyp2 ex2) {<br />

// behandle Fehler-Typ1 und Fehler-Typ 2<br />

}<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 284


Fehlerbehandlung mit Ausnahmen<br />

Mehrere Exceptions<br />

• Ausnahmen werden in den catch-Blöcken in der Reihenfolge ihres Auftretens ausgewertet.<br />

• Abfangen aller möglichen Ausnahmen:<br />

try {<br />

// versuche, eine Aufgabe zu lösen<br />

}<br />

catch (FehlerTyp1 ex) {<br />

// behandle Fehler-Typ1<br />

}<br />

catch (Throwable thr) { // Alle unbehandelten Fehler<br />

// behandle alle anderen Fehler<br />

}<br />

• Ausnahmen können auch im catch-Block ausgelöst werden:<br />

try {<br />

// versuche, eine Aufgabe zu lösen<br />

}<br />

catch (FehlerTyp1 ex) {<br />

// behandle Fehler-Typ1<br />

throw ex; // Fehler weitermelden<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 285


Fehlerbehandlung mit Ausnahmen<br />

Exceptions mit Klassenhierarchien<br />

• Exception-Klassen können ganze Klassenhierarchien bilden.<br />

• Im catch-Block kann auch die Basisklasse einer Ausnahme angegeben werden, um eine<br />

Ausnahme einer abgeleiteten Klasse abzufangen.<br />

• Beispiel:<br />

public class FileNotFoundException extends IOException {<br />

// ...<br />

}<br />

• Eine FileNotFoundException kann jetzt auch durch die Angabe ihrer Basisklasse<br />

abgefangen werden:<br />

public void m() {<br />

try {<br />

// …<br />

throw new FileNotFoundException();<br />

}<br />

catch (IOException ex) {<br />

// …<br />

}<br />

}<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 286


Fehlerbehandlung mit Ausnahmen<br />

Exceptions mit Klassenhierarchien<br />

• Es können auch mehrere catch-Blöcke vorhanden sein, die sowohl die abgeleitete Klasse als<br />

auch die Basisklasse der Ausnahme abfangen. Achtung Reihenfolge:<br />

public void m() {<br />

try {<br />

// ...<br />

throw new FileNotFoundException();<br />

}<br />

catch (IOException ex1) {<br />

// ...<br />

}<br />

catch (Throwable thr) {<br />

// ...<br />

}<br />

}<br />

• Wird erst Throwable abgefangen, dann wird der catch-Block von IOException nie<br />

betreten.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 287


Fehlerbehandlung mit Ausnahmen<br />

Exceptions: Hinweise<br />

• Generelle Ausräumarbeiten nach einem erfolgreichem try oder einer Ausnahme mit<br />

finally. Beispiel:<br />

public void m() {<br />

try {<br />

// ...<br />

throw new FileNotFoundException();<br />

}<br />

catch (IOException ex1) {<br />

// ...<br />

}<br />

finally {<br />

// Wird immer betreten<br />

}<br />

}<br />

• Ein „echtes“ Beispiel folgt im nächsten Kapitel.<br />

• Seit Java 7 gibt es ein erweitertes try-Konstrukt siehe Kapitel zur Ein-<br />

/Ausgabebehandlung.<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 288


Fehlerbehandlung mit Ausnahmen<br />

Exceptions mit Klassenhierarchien<br />

• Arten der Ausnahmen:<br />

• gelb: unerwartete und in der Regel nicht sinnvoll behandelbare Fehler<br />

• grün: unerwartete und in der Regel nicht sinnvoll behandelbare Fehler<br />

(„Programmierfehler“)<br />

• rot: erwartete und sofort oder später behandelbare Fehler (erben direkt von Exception,<br />

nicht von RuntimeException)<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 289


Fehlerbehandlung mit Ausnahmen<br />

Eigenschaften und Deklaration erwarteter Fehler<br />

• Erwartete und sofort oder später behandelbare Fehler (rot markiert):<br />

<br />

<br />

<br />

Einem Anwender einer Methode muss die Art der Ausnahme, die diese auslösen kann,<br />

angegeben werden.<br />

Syntax:<br />

ret-type method-name(params) throws Exceptions<br />

Beispiel:<br />

public int readFromFile(String name) throws FileNotFoundException,<br />

EOFException {<br />

Beispiel durch Angabe der Basisklasse IOException (FileNotFoundException und<br />

EOFException erben davon):<br />

public int readFromFile(String name) throws IOException {<br />

Ohne Spezifikation kann die Methode nur unerwartete oder gar keine Ausnahmen<br />

auslösen.<br />

Beispiel:<br />

public int getValue(int index) {<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 290


Pakete<br />

Übersicht<br />

Java und<br />

UML<br />

Schritte,<br />

Software<br />

Imperative<br />

Aspekte<br />

Klassendiagramme<br />

Objektorientierung<br />

Ausnahmen<br />

Pakete<br />

Klassen,<br />

Objekte<br />

Fehler<br />

Überladen<br />

Zusicherungen<br />

Vererbung<br />

Gener.<br />

Klassen<br />

Überschreiben<br />

Aufzähltypen<br />

Regeln<br />

Holger Vogelsang<br />

<strong>Informatik</strong> 2 - Einführung in Java und UML 291


Pakete<br />

Motivation<br />

• Was passiert, wenn zwei Hersteller Klassen mit demselben Namen erstellt haben und<br />

beide Klassen in einem Projekt zusammen benutzt werden sollen?<br />

• Wie können logisch zusammengehörige Klassen gruppiert werden?<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 292


Pakete<br />

Idee<br />

• Ein Paket sollte eine Anzahl logisch zusammengehöriger Klassen, Schnittstellen, Ausnahmen,<br />

Fehler, Aufzähltypen und Annotationen beinhalten.<br />

Beispiel:<br />

alle Klassen, die mathematische Berechnungen durchführen<br />

alle Klassen, die Text formatieren<br />

• Der Paketname entspricht einem Verzeichnis im Dateisystem.<br />

Beispiel:<br />

Klasse Complex im Paket de.hska.iwii.math: Sowohl die Quelltextdatei Complex.java<br />

als auch die Bytecode-Datei Complex.class sollten in in einem Unterverzeichnis<br />

de/hska/iwii/math liegen.<br />

• Festlegung der Paket-Zugehörigkeit einer Klasse: Anweisung in der Klasse der Form package<br />

Paket-Name;. Diese Anweisung sollte die erste in der Datei sein.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 293


Pakete<br />

Idee<br />

• Verwendung einer Klasse eines anderen Pakets:<br />

Variante 1: import Paketname.*; Beispiel:<br />

<br />

import de.hska.iwii.math.*;<br />

//...<br />

Complex value = new Complex();<br />

// Bindet alle Klassen des Pakets<br />

// de.hska.iwii.math ein<br />

Variante 2: import Paketname.Klassenname; Beispiel:<br />

import de.hska.iwii.math.Complex;<br />

//...<br />

Complex value = new Complex();<br />

// Bindet Complex des Pakets<br />

// de.hska.iwii.math ein.<br />

Variante 3: Verwendung des vollständigen Klassennamens. Beispiel:<br />

//...<br />

de.hska.iwii.math.Complex value = new de.hska.iwii.math.Complex();<br />

• Nach Aussage von Oracle sollte Variante 1 vermieden werden.<br />

• Das Paket java.lang des JDK ist immer automatisch eingebunden.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 294


Pakete<br />

Aufbau<br />

• Allgemeiner Aufbau eines Namens (kann variieren):<br />

Organisation.Paketname.Klassenname.Methodenname<br />

Beispiele:<br />

Paket Klasse Methode<br />

de.hska.ss2012.project2.math.Complex.add()<br />

Land<br />

Hochschule<br />

KA<br />

Semester Projekt Teil des<br />

Projektes<br />

Paket Klasse Methode<br />

com.mycompany.math.Complex.add()<br />

Firma<br />

Teil des<br />

Projektes<br />

Paket Klasse Methode<br />

javax.swing.table.DefaultTableModel.getDataVector()<br />

Kommerziell<br />

Zusatzklasse<br />

des JDK<br />

GUI-<br />

Paket<br />

Tabelle<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 295


Pakete<br />

Inhalte eines Pakets<br />

• Innerhalb eines Pakets müssen die Namen eindeutig sein: Es darf eine Klasse Complex<br />

mehrfach geben, solange sie in unterschiedlichen Paketen liegt.<br />

• Beispiel: java.util.Timer und javax.swing.Timer<br />

• So ganz stimmt die Aussage nicht:<br />

Der komplette Paketname (der Pfad inkl. Klassenname) darf mehrfach vorkommen,<br />

wenn die Pakete durch unterschiedliche Klassenlader (Classloader) geladen werden.<br />

Also: Klassenlader + Paketname muss eindeutig sein!<br />

• Es ist mindestens ein Klassenlader in der virtuellen Maschine aktiv:<br />

Er kennt mehrere Dateipfade oder jar-Dateien, aus denen er die Klassen und<br />

Schnittstellen lädt.<br />

Weitere Klassenlader können erstellt und verwendet werden.<br />

Holger Vogelsang <strong>Informatik</strong> 2 - Einführung in Java und UML 296

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!