Vorlesung Informatik II Universität Augsburg Sommersemester 2011 Prof. Dr. Robert Lorenz Lehrprofessur für Informatik 00. Organisatorisches 1 Ziele Erstellen größerer Softwaresysteme in Java: Objektorientierter Entwurf von Softwaresystemen mit UML Anwenden von Java-Bibliotheken Implementierung von UML-Modellen in Java Selbstständiges Erarbeiten von Problemlösungen Eigenverantwortliches Erarbeiten von Lerninhalten Präsentation von Problemlösungen 2 Wie? Üben, Üben, Üben (wie schon letztes Semester) Übungsblätter bearbeiten Vorrechnen Betreutes Programmieren Angemessen: 6-8 Stunden pro Woche 3 Verwaltungssysteme LectureReg: Verwaltungssystem der Lehrstühle https://peaches.informatik.uni-augsburg.de/lecturereg/ Anmeldung zu Übungsgruppen Anmeldung zu Klausuren Abfrage von Ergebnissen Registrierung, um Rundmails zu erhalten Anmeldefristen: Lehrstuhl-Webpage, Rundmails, Vorlesung 4 Verwaltungssysteme STUDIS: Verwaltungssystem des Prüfungsamts https://www.studis.uni-augsburg.de/studisaugsburg/fai/ Anmeldung zu Prüfungsmodulen Teilnahme an den Klausuren ohne STUDISAnmeldung ist NICHT möglich Anmeldefristen: Lehrstuhl-Webpage, Rundmails, Vorlesung Der Lehrstuhl ist nicht für Studis zuständig Bei Problemen: Prüfungsamt! 5 Vorlesungsbetrieb Zwei Vorlesungen pro Woche im Hörsaal I Dienstag 10:00 – 11:30 Donnerstag 10:00 – 11:30 Vorlesungsfrei 2. + 14. + 23. Juni 6 Vorlesungsbetrieb Folien zur Vorlesung jeweils ab Montag, 12.00 Uhr (Webseite des Lehrstuhls) stehen ausgedruckt zur Verfügung (Studiengebühren) 7 Vorlesungsbetrieb Einführung in die Softwaretechnik (Wirtschaftsinformatiker) Vorlesungen prüfungsrelevant bis einschließlich 9. Juni (5 Übungsblätter) 8 Übungsbetrieb Übungsblätter Wöchentliche Ausgabe Montags, 12 Uhr, Start gestern Bearbeitungszeit: 1 Woche bis Montag, 12 Uhr Abgabe in festen Teams von 2-3 Studenten per Mail an den Tutor der eigenen Übungsgruppe und schriftlich in die Briefkästen des Informatikgebäudes Angabe von Name+Matrikelnummer aller Teammitglieder und Nummer der Übungsgruppe Bewertung: 1 Übungspunkt pro Aufgabe 9 Übungsbetrieb Übungsgruppen 12 Übungsgruppen zu maximal 25 Teilnehmern keine direkte Anmeldung möglich Anmeldung in Vorregistrierungsgruppe und Prioritätensystem Termine: siehe Lecturereg Start ab kommenden Montag, 09.05. Kennenlernen, Fragen und Teambildung 10 Übungsbetrieb Übungsgruppen Wiederholergruppe für Wiederholer ab SS 2009, die nicht am Übungsbetrieb teilnehmen Lehramtsgruppe für Lehrämtler, die nicht am Übungsbetrieb teilnehmen Vorregistrierungsgruppe für alle anderen Anmeldung bis Donnerstag, 05.05., 24 Uhr Angabe von Prioritäten bis Donnerstag, 05.05., 24 Uhr unter http://www.informatik.uni-augsburg.de/EduCoSci/PrioMan-Info2/ Bekanntgabe der Einteilung bis Ende der Woche (Sonntag) 11 Übungsbetrieb Übungsgruppen Bewertung beim Vorrechnen: 1 Übungspunkt pro Aufgabe Einmal Vorrechnen ist Pflicht! 12 Übungsbetrieb Betreutes Üben/Programmieren Bearbeiten zusätzlicher Übungs-/Programmier-Aufgaben mit Unterstützung durch Tutoren Termin: Mittwoch, 14.00 – 19.00 Raum 1001 N Beginn: 04.05. Zusatzaufgabe bringt einen Übungspunkt 13 Übungsbetrieb Globalübung Nach Korrektur eines Übungsblatts Fragen, häufige Fehler, alternative Lösungen, Nachbetrachtungen, kein Vorrechnen Betreuung durch den Lehrstuhl Termin: Dienstag, 8.15 – 9.45, Informatik-Hörsaal 2045 Beginn: 24.5. 14 Prüfungsmodalitäten Für ALLE gilt: Am Semesterende: 1. Klausur Am Semesterende nächstes Semester: 2. Klausur (Reguläre Klausur zu Informatik II im WS) Anmeldung notwendig unter Studis und LectureReg Achtung: Studis-Anmeldung führt zur Bewertung auch bei NichtTeilnahme (als nicht bestanden) Je nach Studiengang unterscheiden sich Anmelde-Modalitäten Anzahl der Prüfungsversuche 15 Prüfungsmodalitäten Für ALLE gilt: Man soll/muss zielgerichtet studieren, d.h. jede Prüfungsmöglichkeit wahrnehmen Nicht zielgerichtet zu studieren hat Nachteile Erhöhung des Lernaufwands (über die Ferien alles vergessen) mehr Überschneidungen mit anderen Veranstaltungen Probleme bei Anträgen auf Fristverlängerung Bereiten Sie sich aus denselben Gründen gleich auf die 1. Klausur gründlich und gewissenhaft vor 16 Prüfungsmodul Informatik I Bachelor Informatik / Informatik & Multimedia, PO 2009: Jede Klausur ist ein eigenes Prüfungsmodul für jede Klausur (Prüfung) ist Studis-Anmeldung erforderlich Man muss jede Prüfungsmöglichkeit nutzen Nach dem 3. Semester müssen alle zur Orientierungsprüfung zählenden Prüfungen bestanden sein dazu zählen Informatik I, Informatik II, Programmierkurs Man hat faktisch zwei Prüfungsversuche Prüfung kann bei Nicht-Bestehen einmal wiederholt werden Sonderregelung: Man kann mit 2. Klausur Note verbessern (gilt u.a. für Informatik 1, Informatik 2) 17 Prüfungsmodul Informatik I Andere Informatik-Studiengänge, Nebenfächler: Jede Klausur ist ein eigenes Prüfungsmodul für jede Klausur (Prüfung) ist Studis-Anmeldung erforderlich Man darf an beiden Klausuren teilnehmen Es zählt die bessere Note aus beiden Klausuren Anzahl der Prüfungsversuche, Obergrenze Semesteranzahl bitte eigene PO lesen! 18 Prüfungsmodul Einf. Softwaretechnik Bachelor Wirtschaftsinformatik: Jede Klausur ist ein eigenes Prüfungsmodul für jede Klausur (Prüfung) ist Studis-Anmeldung erforderlich Es gibt keine Beschränkung der Anzahl der Prüfungsversuche Bei Bestehen kann die Note nicht mehr verbessert werden Informatik 1 / Informatik 2 sind Pflichtveranstaltungen müssen bis spätestens zum 8. Semester bestanden sein Nach dem 2. Semester müssen alle zur Orientierungsprüfung notwendigen Leistungspunkte (30 LP) gesammelt sein Informatik 1 (Informatik 2) können, müssen aber nicht eingebracht werden 19 Klausur Zulassung (gilt für alle trotz unterschiedlicher POs!) Mindestens 20 Übungspunkte (WIN: 10 Punkte) aus… …Bearbeitung von Übungsblättern 1 Punkt für jede richtig bearbeitete Aufgabe 4 Aufgaben pro Übungsblatt …Vorrechnen in den Übungsgruppen 1 Punkt für jede korrekt vorgerechnete Aufgabe Maximal 12 Punkte aus Vorrechnen einbringbar …Bearbeitung der zusätzlichen Aufgabe im betreuten Programmieren 1 Punkt für richtig bearbeitete Aufgabe 20 Klausur Zulassung (gilt für alle trotz unterschiedlicher POs!) Mindestens 1 mal Vorrechnen in der Übungsgruppe Anmeldung zur Klausur in LectureReg und Studis (Anmeldezeiträume werden noch bekannt gegeben) 21 Klausur Bewertung Für je 5 Punkte über der Zulassungsgrenze (20 Punkte / WIN: 10 Punkte) gibt es einen Bonuspunkt es sind bis zu 10 Bonuspunkte erreichbar In der Klausur sind 120 Punkte (WIN: 60 Punkte) erreichbar Zum Klausurergebnis werden die Bonuspunkte hinzugezählt Das Prüfungsmodul ist bestanden mit 50% der Gesamtpunkte (also 60 Punkten / WIN: 30 Punkten) Klausurnote zählt zur Endnote 22 Klausur Alte Zulassungen Zulassungen/Bonuspunkte seit SS 09 bleiben erhalten Zulassungen vor SS 09 zählen nicht Termine 1. Klausur: letzte Veranstaltungswoche, Donnerstag, 28.07. 2. Klausur: Ende WS 23 Software Programmiersprache Java JDK 6 Update 5:http://java.sun.com/javase/downloads/index.jsp API: http://java.sun.com/javase/6/docs/api/index.html Entwicklungsumgebung Eclipse: http://www.eclipse.org 24 Literatur/Materialien Programmiersprache Java Java ist auch eine Insel: Christian Ullenboom, 2006 (http://www.tutego.com/javabuch/) The Java Tutorial: M. Campione, K. Walrath, 1998 (http://java.sun.com/docs/books/tutorial/) Lehrbuch Grundlagen der Informatik: Helmut Balzert, 2005 25 Literatur/Materialien UML (Unified Modeling Language) http://www.oose.de/notationuml14.htm Lehrbuch der Objektmodellierung: Heide Balzert, 2005 Objektorientierte Softwareentwicklung: Bernd Oesterreich, 2001 26 Bei Fragen Lehrstuhl-Webpage http://www.informatik.uni-augsburg.de/lehrstuehle/inf/ E-Mail-Adressen [email protected] [email protected] [email protected] Sprechstunde Mittwoch, 10:00 – 11:00 Raum 1023 N (neues Gebäude) Studentenforum 27 Vorlesung Informatik II Universität Augsburg Sommersemester 2011 Prof. Dr. Robert Lorenz Lehrprofessur für Informatik 01. Softwareentwurf 1 Softwareentwurf Teilgebiet des Software-Engineering Ziel: Systematisierung / Vereinheitlichung des Entwurfs Teilweise computergestützt (Softwareentwicklungstools) 2 Softwareentwurf Forderungen Systematischer und nachvollziehbarer Entwurf zur Erleichterung der Pflege, Wartung und Erweiterung des Programms Arbeitsteiliger Entwurf (bei großen Problemstellungen) - frühzeitige Strukturierung - Zerlegung in Teilprobleme 3 Softwareentwurf Entwurfsprinzipien Allgemeingültige und anerkannte Konzepte, Richtlinien und Techniken des Entwurfs Unterstützen ingenieurmäßige Konstruktion von "guter" Software. die wichtigsten Konzepte sind: - Strukturierung - Schrittweise Verfeinerung - Modularisierung 4 Strukturierung Mit Strukturierung wird eine adäquate Darstellung der logischen Eigenschaften von Daten und Abläufen und der Zusammenhänge zwischen ihnen bezeichnet. 5 Strukturierung Algorithmische Strukturierung (Informatik 1): Strukturierte Darstellung des logischen Ablaufs durch Sequenzen, d.h. lineare Abfolgen von Anweisungen Verzweigungen in Abhängigkeit von Bedingungen Wiederholungen von Anweisungsfolgen 6 Strukturierung Datenstrukturierung (Informatik 1+2): Darstellung der logischen Eigenschaften und Beziehungen zwischen den zu bearbeitenden Objekten durch geeignete Datentypen 7 Strukturierung Vorgehen Elementare Operationen (und Datenstrukturen) einer komplexen Anwendung sind meist sehr einfach. Wenn man die Funktionalitäten einer Anwendung als komplexe Operationen auffasst, die sich aus vielen elementaren Operationen und Ablaufstrukturen zusammensetzen, so stellt sich folgende Frage: Wie gestaltet man den Schritt von den elementaren Operationen zu der komplexen Funktionalität einer Anwendung und umgekehrt möglichst überschaubar und einfach? 8 Schrittweise Verfeinerung Prinzip 1: Top-Down-Vorgehen Programmiersprachen-unabhängiger Entwurf der groben Funktionalität einer Anwendung mit abstrakten Operationen und Datentypen (Benutzerorientiert) Verfeinerung der im ersten Schritt benutzten Operationen, d.h. "Implementierung" mit weniger abstrakten Operationen und Datentypen. Wiederholung des Verfeinerungsschrittes, bis nur noch (Programmiersprachen-abhängig) zur Verfügung stehende Ablaufstrukturen und Elementaroperationen verwendet werden. 9 Schrittweise Verfeinerung Prinzip 1: Top-Down-Vorgehen Erfordert simultane, aufeinander abgestimmte Verfeinerung und Konkretisierung von: – Operationen, – Kontrollflüssen (Ablaufstrukturen), – Datenstrukturen d.h. die einzelnen Bestandteile von Algorithmen sollten auf gleichem Niveau verfeinert werden. 10 Modularisierung Prinzip 2: Bottom-Up-Vorgehen (Informatik 1) Abgeschlossene Teilaufgaben werden zuerst durch Programmstücke realisiert. Anschließend Zusammenfügen der Teillösungen zu größeren Einheiten. Erfordert Modularisierung des Problems in Teilprobleme (Teilaufgaben) 11 Modularisierung Beispiele für Bottom-Up-Vorgehen aus Informatik 1 Mathematische Aufgabenstellungen: zunächst einfache arithmetische Operationen später komplizierte Operationen (Matrizenrechnung, numerische Integration) Erstellung von Programmbibliotheken: zunächst einfache Standardalgorithmen spätere Verwendung beim Entwurf komplizierter Algorithmen 12 Modularisierung Definition Modularisierung Zerlegung von Problemen in Teilprobleme, die – klar voneinander abgegrenzt sind – getrennt bearbeitet werden können – weitgehend unabhängig voneinander sind – deren Lösungen nebenwirkungsfrei gegen Alternativlösungen austauschbar sind (keine "Seiteneffekte"). 13 Modularisierung Vorteile Reduzierung der Komplexität eines Problems durch Zerlegung in überschaubare Einzelprobleme Einzelne Module können unabhängig voneinander getestet oder verifiziert werden Einzelne Module sind austauschbar und erweiterbar (Baukastenprinzip) Erlaubt unproblematischen Übergang zu Nachfolgeversionen eines Softwareprodukts durch Austausch einzelner Module 14 Modularisierung Charakteristika von Modulen: Keine Berücksichtigung von Reihenfolgeabhängigkeiten (im Unterschied zur schrittweisen Verfeinerung) Spezifikation weitgehend unabhängiger Teilaufgaben mit klar definierten Schnittstellen (Prinzip der Einkapselung) Späteres Zusammenfügen der einzelnen Teillösungen über die vereinbarten Schnittstellen 15 Modularisierung Prinzip der Einkapselung Zusammenfassung bestimmter Programmteile (Daten, Funktionen) Bereitstellung einer bestimmten Funktionalität Implementierung für den Anwender nicht wichtig Schutz dieser Programmteile vor direktem Zugriff Implementierung darf nicht verwendet werden (wegen Austauschbarkeit) Aufruf nur über fest definierte Schnittstelle Sicherstellung von Datenstruktur-Invarianten 16 Modularisierung Datenstruktur-Invariante Eine Eigenschaft einer Datenstruktur, die nach Initialisierung gilt und durch alle Operationen darauf erhalten bleiben soll, heißt Invariante der Datenstruktur. Durch beliebigen Zugriff kann ein Zusammenhang zwischen den beteiligten Variablen gestört werden. (Bsp.: Fallstudie am Ende) 17 Modularisierung Beispiel für Einkapselung: Funktionen (siehe Informatik 1) Wiederholt ausgeführte, ähnliche Teile werden durch Parametrisierung zusammengefasst Implementierung stellt Datenstruktur-Invarianten sicher Implementierung ist für den Anwender einer Funktion nicht wichtig, sondern die Funktionalität Benutzung über die Schnittstelle von Eingabe- und Ausgabeparametern Aber: Funktionen reichen nicht, um Größen durch Einkapselung vor beliebigem Zugriff zu schützen (Bsp.: Fallstudie am Ende) 18 Modularisierung Definition Modul Ein Modul besteht aus einer Sammlung von VariablenVereinbarungen und Funktionen Variablen und Funktionen werden in öffentliche und private aufgeteilt. Die öffentlichen sind außerhalb des Moduls verfügbar, die privaten nur innerhalb (diese sind also eingekapselt) Kein beliebiger Zugriff auf private Variablen und Funktionen 19 Modularisierung Typische Realisierung von Modulen Eine Datenstruktur wird meist als Sammlung privater Variablen realisiert Die öffentlichen Funktionen werden dann so angelegt, dass sie die erwünschten Datenstrukturinvarianten erhalten Damit ist der unkontrollierte Zugriff auf private Variable unterbunden 20 Modularisierung Schnittstelle eines Moduls Die Sammlung der öffentlichen Variablen und FunktionsDeklarationen eines Moduls nennt man dessen Schnittstelle (interface). Angabe durch die Signatur: Bezeichner der Variablen und Konstanten mit Typ Prototypen der Funktionen Beispiel: h-Datei in C 21 Modularisierung Fallstudie: Implementierung einer Menge ganzer Zahlen Öffentlicher Teil der Schnittstelle für eine Datenstruktur Set zur Repräsentation von Mengen in C: Set * emptyset(); Initialisierung leere Menge int iselem (int, Set *); Enthaltensein eines Elements Set * insert (int, Set *); Einfügen eines Elements Set * delete (int, Set *); Löschen eines Elements Set * union (set *, Set *); Vereinigung von Mengen Set * intersection (Set *,Set *); Durchschnitt von Mengen int getsize (Set *); Größe einer Menge void printset (Set *); Ausgabe einer Menge 22 Modularisierung Fallstudie: Implementierung einer Menge ganzer Zahlen Implementiere Set als einfach verkettete Liste: typedef struct knoten { int wert; struct knoten * next; } Knoten; typedef struct set { knoten * start; int size; } Set; 23 Modularisierung Fallstudie: Implementierung einer Menge ganzer Zahlen Implementiere Set als einfach verkettete Liste: Datenstrukturinvarianten: „Liste sortiert und wiederholungsfrei“ „Wert von size entspricht Anzahl der Knoten“ Leere Menge: Menge {1,2,4}: null 1 2 4 null 24 Modularisierung Fallstudie: Implementierung einer Menge ganzer Zahlen Implementiere Set als Bitvektor fester Länge: typedef struct set { int werte[1000]; int size; } Set; 25 Modularisierung Fallstudie: Implementierung einer Menge ganzer Zahlen Implementiere set als Bitvektor fester Länge: Datenstrukturinvarianten: „Vektor werte hat nur die Werte 0 und 1“ „Wert von size entspricht Anzahl der 1sen im Vektor werte“ Leere Menge: Vektor 0 Index Menge {1,2,4}: Vektor Index 0 0 0 0 0 ... 0 1 2 3 4 5 ... 0 1 1 0 1 ... 0 1 3 4 ... 2 26 Modularisierung Fallstudie: Implementierung einer Menge ganzer Zahlen DISKUSSION: Welche Implementierung ist (in welchen Fällen) weniger Speicherplatz- bzw. Zeitaufwendig? Überlege verschiedene Möglichkeiten, wie ein Programmierer dummerweise Datenstruktur-Invarianten zerstören könnte ZUSÄTZLICHE SPRACHKONSTRUKTE FÜR EINKAPSELUNG NOTWENDIG 27 Modularisierung Zusammenfassung Zerlegung eines großen Programmsystems in einzelne, überschaubare und sinnvolle Teile Abschirmung und damit Schutz privater Variablen Verbergen von Implementierungsdetails: Trennung „Was wird getan“ (deklarativ) von „Wie wird es getan“ (operationell) Austauschbarkeit von Implementierungen Möglichkeit zur unabhängigen Implementierung der Teile, wenn die Schnittstellen geklärt sind. 28 Modellbasierter Entwurf Entwicklung komplexer Anwendungen benötigt Strukturierung Modellbildung vor Programmierung UML (Unified Modeling Language) zur Programmiersprachenunabhängigen Modellierung komplexer Systeme: Statische Modelle: Strukturierung der Daten (Klassendiagramm) Dynamische Modelle: Strukturierung der Abläufe (Sequenzdiagramm) 29 UML Charakteristika: Modellierungssprache zur Dokumentation von Analyse, Entwurf und Implementierung objektorientierter Software Vereinigt eine Vielzahl graphischer und textueller Beschreibungsmethoden (Diagrammtypen) Beinhaltet kein Vorgehensmodell zur Software-Entwicklung, gibt aber einen Rahmen vor. Vorteile: Unabhängigkeit von Programmiersprache Graphische Darstellung (verständlich für Anwender) 30 UML UML in dieser Vorlesung Sprachumfang zu umfangreich zur Darstellung in einer Vorlesung Viele Details erst in der Anwendung voll verständlich Vorlesung ist keine vollständige UML-Dokumentation! Stattdessen: Einführung in Grundkonzepte der wichtigsten Diagrammtypen (Klassen-, Sequenz-Diagramm) Entwicklung einer Basis für Entwicklung einfacherer Anwendungen und selbstständige detailliertere Einarbeitung 31 Ein Vorgehensmodell zur Modellierung Top-Down-Vorgehen grob in 3 Phasen: Analyse Was soll gemacht werden? (UML) Entwurf Wie wird’s gemacht? (UML) Implementierung (konkrete Programmiersprache) Test 32 Ein Vorgehensmodell zur Modellierung Analyse Pflichtenheft Analysemodell Prototyp Entwurf Entwurfsmodell Benutzeroberfläche Fachkonzept Analysemodell Datenhaltung Bibliotheken Datenbank (Java-)Programm 33 Ein Vorgehensmodell zur Modellierung Manche Diagramme lassen sich eindeutig einer der Modellierungsphasen (Analyse, Entwurf) zuordnen Andere Diagramme werden in beiden Phasen verwendet, in der Analyse werden aber nicht alle Aspekt berücksichtigt Die Trennung in Analyse und Entwurf erfährt man am besten in der Praxis Wir werden das Vorgehensmodell und die Trennung in Analyse- und Entwurfsphase nicht besprechen 34 Ein Vorgehensmodell zur Modellierung Sinn, Zweck und Bedeutung von Vorgehensmodellen „Die Qualität eines Programms kann nicht im Nachhinein ‚hineingetestet‘ werden“ (Produktverbesserung durch Prozessverbesserung, d.h. durch Verbesserung der methodischen Vorgehensweise zur Erstellung eines Produkts) „If you wait for a complete and perfect concept to germinate in your mind, you are likely to wait forever“ (deMarco) (Die Methodik soll eine Hilfsstellung sein und nicht zu bürokratisch ausgelegt werden) 35 Ein Vorgehensmodell zur Modellierung Womit fängt man an? Beschreibung der Systemidee in 5-20 Sätzen: Was soll mit dem System erreicht werden (nicht wie wird das Ziel erreicht) Dokumentenanalyse: Formulare, Bedienungsanleitungen, Fragebögen, … Re-Engineering: Anleitungen, Hilfesystem, Bildschirmmasken, Benutzerdialoge, Funktionalität Pflichtenheft: Textuelle Beschreibung dessen, was das System leisten soll, detaillierter als das Analysemodell 36 Vorlesung Informatik II Universität Augsburg Sommersemester 2011 Prof. Dr. Robert Lorenz Lehrprofessur für Informatik 02. JAVA: Erstes Programm 1 Das erste Java-Programm /** Ausgabe des Zeichenkette „Hello World“ (Mehrzeiliger Kommentar zur aut. Erstellung von Dokumentationen) */ //Ein Modul (Klasse SayHello) (einzeiliger Kommentar) class SayHello { //Variablen (Attribute): keine //Deklaration von Operationen (Funktionen): //Funktion main mit Übergabe von Kommandozeilenparametern public static void main(String args[]) { //Bibliotheksfunktion println des Objekts System.out System.out.println(“Hello World“); } } 2 Das erste Java-Programm class SayHello { ... } Deklaration einer Klasse SayHello Eine Klasse ist ein strukturierter Datentyp (ein Modul) Eine Klasse besteht aus der Deklaration von Variablen und Funktionen (müssen Teil einer Klasse sein) Die Variablen einer Klasse heißen Attribute Die Funktionen einer Klasse heißen Operationen Jede Klasse in Java wird in einer eigenen java-Datei vereinbart (Klassen- und Dateiname müssen übereinstimmen) 3 Das erste Java-Programm class SayHello { ... } Deklaration einer Klasse SayHello Es können beliebig viele Variablen einer Klasse vereinbart werden Diese Variablen heißen Objekte Operationen können nur über Objekte aufgerufen werden (Ausnahme: Klassenoperationen) 4 Das erste Java-Programm class SayHello { ... } Ein C-Programm besteht aus einer Sammlung von Funktionen In C gibt es strukturierte Datentypen, die aber nur Daten kapseln In C sind Funktionen keinen Daten zugeordnet Ein Java-Programm besteht aus einer Sammlung von Klassen In Java werden durch Klassen Daten und Funktionen gekapselt In Java sind Funktionen nur über Objekte der zugehörigen Klasse aufrufbar 5 Das erste Java-Programm public static void main(String args[ ]) { ... } Deklaration der Operation main Genau eine der Klassen eines Programms muss die mainFunktion enthalten (die Programmklasse) Bei Start wird automatisch main aufgerufen 6 Das erste Java-Programm public static void main(String args[ ]) { ... } Deklaration der Operation main main hat immer folgende Modifikatoren: public: öffentliche Operation – von aussen aufrufbar static: Klassenoperation – ohne Objekt aufrufbar [man benötigt kein Objekt der Programmklasse für den Aufruf] 7 Das erste Java-Programm public static void main(String args[]) { ... } Deklaration der Operation main main hat immer folgende Parameter: void: kein Rückgabewert String args[]: Feld (Array) args von Objekten der Klasse String args repräsentiert wie in C Kommandozeilenparameter String ist Klasse zu Repräsentation von Zeichenketten 8 Das erste Java-Programm public static void main(String args[ ]) { ... } Ein C-Programm enthält genau eine Funktion main In C werden Zeichenketten durch Pointer auf char repräsentiert (char *) Ein Java-Programm enthält genau eine Klasse mit der Funktion main In Java gibt es für Zeichenketten die Klasse String 9 Das erste Java-Programm { ... } - Blöcke Geben wie in C Gültigkeitsbereiche an Beispiele: Klassenrümpfe, Funktionsrümpfe 10 Das erste Java-Programm System.out.println(...); Aufruf der Bibliotheksfunktion println println gibt übergebene Zeichenkette auf Kommandozeile aus System ist eine Bibliotheksklasse System hat ein Attribut out Zugriff auf Attribute einer Klasse mit “.” - Notation out ist Objekt der Bibliotheksklasse PrintStream PrintStream hat eine Operation println(...) Zugriff auf Operationen eines Objekts mit “.” – Notation 11 Das erste Java-Programm System.out.println(...); Aufruf der Bibliotheksfunktion println println gibt übergebene Zeichenkette auf Kommandozeile aus Bibliotheksklassen sind hierarchisch in Pakete gegliedert: Das Paket java enthält alle anderen Pakete Das Paket lang im Paket java enthält alle Basisklassen System ist eine Klasse im Paket lang Das Paket lang wird automatisch geladen (andere Pakete muss man manuell einbinden) 12 Das erste Java-Programm System.out.println(...); In C gibt es eine Funktions-Bibliothek (gegliedert in h-Dateien) In Java gibt es eine Klassen-Bibliothek (hierarchisch gegliedert in Pakete): http://java.sun.com/javase/6/docs/api/ 13 Compilieren und Ausführen Vorgehen 1. Java-Programme werden von einem Prozessor-unabhängigen Java-Compiler in sog. Byte-Code übersetzt. Dieser kann vom Prozessor nicht direkt ausgeführt werden. 2. Der Byte-Code wird von einem System-spezifischen Interpreter ausgeführt. Der Java-Interpreter verdeckt die Eigenschaften des jeweiligen Prozessors und bietet eine höhere Abstraktionsschicht, die man sich als gedachten (virtuellen) Prozessor vorstellen kann man spricht von der Java Virtuellen Maschine (JVM) 14 Compilieren und Ausführen Vorgehen Erstelle .java - Quelldateien mit Texteditor Compiliere Dateien mit Kommandozeilen-Befehl javac <Dateiname>.java Ergebnis: Ausführbarer Byte-Code in class- Dateien Führe Programm aus durch Interpretation der class – Programmdatei mit Kommandozeilen-Befehl java <Programmdateiname>.class 15 Compilieren und Ausführen Vorteile: Nur ein Compiler für alle Prozessortypen Java plattform-unabhängig exakt definiert Übersetzte Java-Programme laufen ohne Neuübersetzung auf allen Plattformen mit Java-Interpreter Nachteile: Übersetzte Programme laufen langsamer Für jeden Prozessortyp einen neuen Interpreter 16 Compilieren und Ausführen Anleitung Installiere Java SE JDK 6 (auch J2SE SDK genannt) Download unter http://java.sun.com Jetzt müssen folgende Kommandos (Kommandozeilenfenster) ein erfolgreiches Ergebnis liefern: C:\Java\jdk\bin\java.exe -version C:\Java\jdk\bin\javac.exe -help Mit javac wird der Java-Compiler aufgerufen Mit java wird ein Java-Programm ausgeführt 17 Compilieren und Ausführen System konfigurieren Setzen von Umgebungsvariablen: Angabe von Pfaden ... ... wo das Betriebssystem nach Compiler/Interpreter sucht ... wo Compiler/Interpreter nach Klassendateien suchen Benutzervariablen setzen: JAVA_HOME C:/Programme/Java/jdk1.6.0_06 Systemvariablen erweitern um: Path <vorhandenePfade>; C:/Programme/Java/jdk1.6.0_06; C:/Programme/Java/jdk1.6.0_06/bin 18 Compilieren und Ausführen System konfigurieren Jetzt müssen folgende Kommandos erfolgreich sein: set JAVA_HOME java -version javac -help 19 Mehr Java-Programme class SayWhat { public static void main(String args[]) { if (0 < args.length)//Fallunterscheidung nach Länge von args { int i; for (i=0;i<args.length;i=i+1) //for-Schleife über Anzahl Parameter { System.out.println(args[i]);//Zeilenweise Ausgabe der Parameter } } else { System.out.println(“fehlende Argumente”); } } } 20 Mehr Java-Programme public static void main (String args[]) Zugriff auf Kommandozeilenparameter mit args Zugriff auf i-ten Parameter mit args[i-1] Compileraufruf: javac SayWhat.java Interpreteraufruf: java SayWhat param1 param2 ... (Entspricht args = (param1, param2, ... )) 21 Mehr Java-Programme public static void main (String args[]) Ähnlich wie in C: Deklaration von i gilt nur lokal im { ... } - Block if-else- Anweisung für Fallunterscheidungen for- Anweisung für wiederholte Ausführung von Anweisungen Unterschiedlich zu C: Mit Feldname.length kann man die Länge eines Feldes abfragen 22 Eclipse Eclipse bietet eine Entwicklungsumgebung für Java (und andere Programmiersprachen) Frei erhältlich (open source) unter www.eclipse.org .zip-Datei downloaden und in beliebigem Verzeichnis entpacken (z.B. unter C:\...\Java) Achtung: vorher JDK installieren Start: Ausführen von eclipse.exe Workspace am besten auf Datenpartition D: anlegen 23 Eclipse Programme erstellen und ausführen in Eclipse: Java-Projekt anlegen Klasse anlegen mit main-Methode (und Paket-Angabe) Programm schreiben und speichern (wird automatisch compiliert) Fehler beheben (Problems-Tab) und erneut speichern Ausführen mit dem grünen Pfeil (bei Textcursor in main()) Ausgabe im Console-Tab 24 Vorlesung Informatik II Universität Augsburg Sommersemester 2011 Prof. Dr. Robert Lorenz Lehrprofessur für Informatik 03. JAVA: Grundlagen 1 Primitive Datentypen Es gibt diesselben primitiven Datentypen wie in C Zusätzlich: boolean für Wahrheitswerte byte für Bytes Die Wertebereiche sind ähnlich wie in C festgelegt Es sind diesselben Operatoren wie in C anwendbar Details: Jeder deklarierten Variable wird voreingestellter Wert zugewiesen char: 2 Bytes, nicht-negativ, Unicode hexadezimal byte, short, int, long: Wertebereiche symmetrisch zu 0 byte, short, int, long: 2-Komplement-Darstellung 2 Primitive Datentypen Überblick Name Wertebereich Voreinstellung Operatoren boolean {true,false} false byte 1 Byte 0 short 2 Byte 0 int long char float double 4 8 2 4 8 0 0L \u0000 0.0f 0.0d ==,!=,&,|,^, &&,||,! +,-,+,*,/,%,<, <=,>,>=,==,!=, ~,++,-+,-,+,*,/,%,<, <=,>,>=,==,!=, ++,-... ... ... ... ... Byte Byte Byte Byte Byte 3 Primitive Datentypen Konstanten ähnlich wie in C: 012 0x3F 12 -5 3L 3.7 1.2e+2 'A' \b,\n,\t \", \', \\ \0??? \u???? (Oktalzahl) (Hexadezimalzahl) (positive ganze Zahl) (negative ganze Zahl) (ganze Zahl als long-Wert) (Fließkommazahl) (Exponentialdarstellung) (Buchstabe) (Backspace, Newline, Tabulator) (Sonderzeichen) (Oktalzeichen, 0000 <= 0??? <= 0377) (Unicode-Zeichen, u0000 <= u???? <= uFFFF) 4 Primitive Datentypen Operatoren ähnlich wie in C: Arithmetische Operatoren: Bitarithmetische Operatoren: Logische Operatoren: Vergleichsoperatoren: Zuweisungsoperatoren: Bedingungsoperator: ++, --, +/-, *, /, %, +, ~, <<, >>, >>>, &, |, ^ !, &, ^, |, &&, || <, >, <=, >=, ==, != =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>= ?: Operatoren sind überladen, d.h. abhängig vom Datentyp Festgelegte Auswertungsreihenfolge (aber anders wie in C!) * kann nicht zum Dereferenzieren von Pointern benutzt werden! (in Java ist kein direkter Zugriff auf Pointer möglich – später mehr) In Ausdrücken kommt es wie in C zu automatischen Typumwandlungen 5 Primitive Datentypen Automatische Typausweitungen (falls sich in einem Ausdruck Variablen unterschiedlichen Typs befinden) byte short char int long float nach nach nach nach nach nach short, int, long, float, double int, long, float, double int, long, float, double long, float, double float, double double 6 Primitive Datentypen Deklaration wie in C: boolean b = true;//mit Wertzuweisung int i, j;//ohne Wertzuweisung double d = 3.14; char c = 'A'; Durch Deklaration wird der notwendige Speicherplatz für Datentyp reserviert 7 Primitive Datentypen Wertzuweisungen wie in C: boolean b = true;//in der Deklaration b = false;//nach der Deklaration Durch Zuweisung wird einer Variablen ein Wert zugewiesen: Dieser Wert wird also an der reservierten Speicherstelle eingetragen/gespeichert Der Wert kann nur aus dem zugehörigen Wertebereich des Datentyps kommen: Wie in C kommt es zu automatischen Wertumwandlungen (Ausweitung oder Einengung) 8 Primitive Datentypen Explizite Typeinengung durch eine Typcast mittels vorangestelltem (Typ): int i; float b=10.5f; i = (int) b*3;//Wert von i ist 30 (u.U. mit Informationsverlust) 9 Primitive Datentypen Zeiger: In Java gibt es keine Zeiger auf Variablen primitiven Datentyps Parameterübergabe an Funktionen In Java werden Variablen primitiven Datentyps grundsätzlich nach dem “call by value”-Prinzip übergeben (es wird also im Funktionsrumpf mit einer lokalen Kopie gerechnet) Rückgabewerte von Funktionen In Java werden bei primitiven Rückgabetypen grundsätzlich Werte zurückgegeben (niemals Zeiger) 10 Referenz-Datentypen Alle anderen Datentypen sind Klassen oder Felder Beispiele vordefinierte Klassen: String, System, PrintStream, ... (Attribute und Operatoren können der API entnommen werden) Selbstdefinierte Klassen: Siehe UML-Teil Alle Klassen und Felder sind sog. Referenz-Datentypen 11 Klassen Deklaration wie bei primitiven Typen: <Typ> <Vname> Frame f;//ohne Wertzuweisung Variablen einer Klasse sind immer Zeiger Bei der Deklaration wird Speicherplatz für einen Zeiger reserviert 12 Klassen Deklaration wie bei primitiven Typen: <Typ> <Vname> String s = new String(“Du”);//mit Wertzuweisung Durch new wird dynamisch Speicherplatz für ein Objekt einer Klasse reserviert Die Variable ist ein Zeiger auf diesen Speicherplatz Nach new folgt ein sog. Konstruktor Ein Konstruktor ist eine Operation mit dem gleichen Namen wie die Klasse Ein Konstruktor nimmt eine Initialisierung der Attribute des Objekts vor Konstruktoren können vom Benutzer definiert werden Entspricht in etwa dynamischer Speicherreservierung in C 13 Klassen Wertzuweisungen String s;//Deklaration s = new String(“Hallo”);//Zeiger auf Zeichenkette String t = s;//t zeigt auf diesselbe Stelle wie s s = null;//Null-Referenz: s zeigt nirgendwohin Eine Referenz in Form der Speicheradresse des Objekts der rechten Seite wird in der Variable der linken Seite gespeichert null ist die Nullreferenz (entspricht NULL in C) null ist die Voreinstellung bei Klassen 14 Klassen Wertzuweisungen StringBuffer s1 = new StringBuffer(“Hallo”); //s1 zeigt auf Speicherstelle mit Eintrag “Hallo” StringBuffer s2 = new StringBuffer(“World”); //s2 zeigt auf Speicherstelle mit Eintrag “World” Stringbuffer ist eine weitere vordefinierte Bibliotheksklasse zur Verwaltung von Zeichenketten 15 Klassen Wertzuweisungen s2 = s1; //s1 und s2 zeigen auf Speicherstelle mit Eintrag “Hallo” s2.append(“Du”); //s1 und s2 zeigen auf Speicherstelle mit Eintrag “HalloDu” append ist eine Operation der Klasse StringBuffer append erweitet den Speicherbereich und hängt eine Zeichenkette hinten an 16 Klassen Zeiger: Alle Variablen einer Klasse sind Zeiger Parameterübergabe an Funktionen In Java werden Variablen einer Klasse grundsätzlich nach dem “call by reference”-Prinzip übergeben (damit sind die Objekte im Funktionsrumpf manipulierbar, aber natürlich nicht die Zeiger selbst) Rückgabewerte von Funktionen In Java werden bei Klassen-Rückgabetypen grundsätzlich Zeiger zurückgegeben (niemals die Objekte selbst) 17 Klassen Parameterübergabe und Rückgabewerte StringBuffer test(StringBuffer s1,StringBuffer s2) { s1 = s2.append(s1); return s1; } public static void main(String args[]){ StringBuffer s1 = new StringBuffer(“Hallo”); StringBuffer s2 = new StringBuffer(“World”); StringBuffer s3 = test(s1,s2); } s1 zeigt auf Speicherstelle mit Eintrag “Hallo” s2 zeigt auf Speicherstelle mit Eintrag “WorldHallo” s3 zeigt auf Speicherstelle mit Eintrag “WorldHallo” 18 Klassen Typumwandlungen Unter bestimmten Umständen können Klassen ineinander umgewandelt werden Mehr dazu im UML-Teil (Ober- und Unterklassen) 19 Arrays (Felder) Wie in C kann man Felder beliebigen Datentyps mit fester Länge definieren Wie in C sind Feld-Variablen Zeiger Deklaration: <Typ> <meinArray>[] Sorgt für Speicherreservierung für einen Zeiger auf <Typ> Initialisiert den Zeiger auf null (im Unterschied zu C) Längenfestlegung und Speicherreservierung für das Feld erst bei Erzeugung (im Unterschied zu C) 20 Arrays Wie in C kann man Felder beliebigen Datentyps mit fester Länge definieren Wie in C sind Feld-Variablen Zeiger Erzeugung: <meinArray> = new <Typ>[<Länge>] Reserviert Speicherplatz für alle Elemente des Feldes Der Wert der Variable ist ein Zeiger auf diesen Speicherplatz (auf das erste Feldelement) 21 Arrays Wie in C kann man Felder beliebigen Datentyps mit fester Länge definieren Wie in C sind Feld-Variablen Zeiger Zugriff auf Elemente über Index: <meinArray>[i] Ist ein Name für das (i+1)-te Element des Feldes (man fängt wie in C bei 0 zu zählen an) Im Unterschied zu C ist keine explizite Zeigerarithmetik (Adressverschiebung) möglich Java-Programme sollen Plattform-unabhängig und portabel sein 22 Arrays Beispiele int[] meinArray = { 3, 5, 9 }; int[] meinArray = new int[20]; int[][] arr2D = new int[9][8]; String[] arr = { "ab", "mn", "xy" }; String[] arr = new String[2]; MyClass[] myArr = new MyClass[22]; myArr[i] = new MyClass(); 23 Arrays Weitere Besonderheiten: Länge eines Arrays abfragbar mit <Variablename>.length: int n = meinArray.length; Felder kopieren mit System.arraycopy: System.arraycopy(arr1,0,arr2,0,arr2.length); Vordefinierte Bibliotheksklassen für Felder variabler Länge und gemischten Typs: LinkedList, ArrayList, HashSet, TreeSet, HashMap, TreeMap, Vector, ... (siehe später auch UML) 24 Zeiger Zusammenfassung In Java gibt es keine explizite Dereferenzierung Es gibt keine Zeiger auf Werte primitiven Typs Alle Variablen nichtprimitiven Typs sind Zeiger Für Variablen nichtprimitiven Typs wird mit new <Konstruktor>(<Parameterliste>) Speicherplatz für ein Objekt des Typs reserviert und werden die Komponenten initialisiert 25 Zeiger Zusammenfassung Nicht mehr benutzter, dynamisch reservierter Speicherbereich wird automatisch wieder freigegeben (Garbage Collection) Löschung von Objekten, auf die kein Zeiger mehr zeigt dazu: Variablen von unbenötigten Objekten immer nullReferenz zuweisen! 26 Funktionen Funktionen sind immer Teil einer Klasse Deklaration Genauso wie in C in der Form <Rückgabetyp> <Funktionsname>(<Parameterliste>) mit <Parameterliste> := <Typ1> <Parameter1>, ... 27 Funktionen Funktionen sind immer Teil einer Klasse Aufruf Über Punkt-Operation, angewendet auf Variable der Klasse oder den Klassennamen selbst bei static-Funktionen: <Variable>.<Funktionsname>(<Werte>) <Klassenname>.<Funktionsname>(<Werte>) Ähnlich wie Zugriff auf Komponenten von strukturierten Datentypen in C Wie in C müssen Werte zu Eingabeparametern passen 28 Kontrollstrukturen Fallunterscheidungen wie in C: if(<Bedingung>) { <Anweisungen> } else { <Anweisungen> } switch(<Ausdruck>){ case <Wert>: <Anweisungen> default: <Anweisungen> } 29 Kontrollstrukturen Wiederholungen wie in C: while(<Bedingung>) { <Anweisungen> } do { <Anweisungen> } while(<Bedingung>); for(<Wertzuweisung>;<Bedingung>;<Anweisung>) { <Anweisungen> } 30 Hüllklassen Java stellt Hüllklassen (wrapper classes) für die primitiven Datentypen zur Verfügung: Konstruktoren machen aus Elementen primitiven Typs Objekte: public <Hüllklasse> (<Datentyp> <value>) Umkehrmethoden gewinnen die Elemente primitiven Typs zurück: public <Datentyp> <Datentyp>Value() Verfügbare Hüllklassen: Boolean (zu boolean), Character (zu char), Number (abstrakte Oberklasse für alle Zahlklassen), Integer (zu int), Long (zu long), Float (zu float), Double (zu double) 31 Zeichenketten Im Gegensatz zu C gibt es in Java für Zeichenketten eigene Datenstrukturen Für die Repräsentation von Zeichenketten gibt es vordefinierte Bibliotheksklassen Diese Klassen definieren verschiedene Zeichenketten-Operationen verschiedene Konstruktoren zur Erzeugung von Zeichenketten-Objekten 32 Zeichenketten Klasse String repräsentiert Zeichenketten mit zahlreichen Operationen Zeichenketten sind konstant, d.h. es gibt keine Operationen zum Ändern einer einmal konstruierten Zeichenkette 33 Zeichenketten Klasse String Konstruktoren (Auswahl) String() String(char[] value) wandelt das char-Feld value in einen String um String(String value) Kopierkonstruktor String(StringBuffer buffer) Wandelt buffer in einen String um 34 Zeichenketten Klasse String Operationen (Auswahl) int length()//Länge char charAt (int index)//Buchstabe an Position index String toUpperCase()//Umwandlung in Großbuchstaben int compareTo (String anotherString)//Lexikographisch vergleichen boolean startsWith(String prefix)//Ist prefix ein Anfangsstück? int indexOf(int ch)//Erster Index eines Zeichens String substring(int beginIndex, int endIndex)//Substring String concat (String str)//String str anhängen String replace(char oldChar, char newChar)//Buchstaben ersetzen //…u.v.m. 35 Zeichenketten Klasse String Operationen zur Typumwandlung static String valueOf(<Typ> val) Umwandlung nach String für jeden Grundtyp <Typ> außer byte und short <Hüllklasse>(String str) Umwandlung von String in Hüllklasse char[] toCharArray() Umwandlung in ein neues char-Feld (und einige mehr) 36 Zeichenketten Klasse StringBuffer Repräsentiert dynamische Zeichenketten, die nach ihrer Konstruktion beliebig modifiziert werden können. Initialisierung mit einer leeren Zeichenkette fester Länge 37 Zeichenketten Klasse Stringbuffer Operationen (Auswahl) StringBuffer insert(int offset, Object obj)//Einfügen Objekt StringBuffer insert(int offset, String str) //Einfügen String StringBuffer insert(int offset, float f) //Einfügen Zahl StringBuffer insert(int offset, int i) //Einfügen ganze Zahl StringBuffer delete(int start, int end)//Entfernen von Zeichen StringBuffer deleteCharAt(int index)/Entfernen eines Zeichens int capacity()//liefert Kapazität der Speicherstelle int length() //liefert die Länge der aktuellen Zeichenkette char charAt(int index)//liefert ein Zeichen …(u.v.m.) 38 API Application Programming Interface http://java.sun.com/j2se/1.4.2/docs/api/ Klassenbibliothek mit vordefinierten Java-Klassen Aufgeteilt in Pakete, u.a.: java.lang //Basisklassen (Automatisch eingebunden) System, Thread, Zeichenketten,... java.util //Utilities Häufige Datenstrukturen, Zeit/Datum, Zufallszahlen,... java.io //Ein- und Ausgabe Datenströme (Ein-/Ausgabe), Lesen/Schreiben von Dateien,... java.awt //grafische Ausgabe Fenster, Schaltflächen, Textfelder, Menüs, ... 39 API Application Programming Interface http://java.sun.com/j2se/1.4.2/docs/api/ Klassenbibliothek mit vordefinierten Java-Klassen Import von Paketen der API am Programmanfang: import paketname.*; Macht Klassen und Funktionen benutzbar Ähnlich dem include-Befehl in C 40 Vorlesung Informatik II Universität Augsburg Sommersemester 2011 Prof. Dr. Robert Lorenz Lehrprofessur für Informatik 04. UML – Objekte und Klassen 1 Motivation UML bietet die Möglichkeit, programmiersprachenunabhängig strukturierte Datentypen, sog. Klassen, zu definieren Die Variablen eines solchen Datentyps heißen Objekte Klassen und Beziehungen zwischen Klassen lassen sich grafisch im sog. Klassendiagramm darstellen Das Klassendiagramm dient als statisches Modell der Strukturierung der Daten einer Anwendung 2 Motivation Wir werden die Begriffe Objekt, Klasse und Klassendiagramm jetzt so präzise wie möglich (wie gesagt unabhängig von irgendeiner Programmiersprache) klären Wir werden allerdings nicht alle Details von Klassendiagrammen betrachten, sondern nur die wichtigsten Aspekte Später sehen wir, wie man ein Klassendiagramm in Java implementieren kann 3 Objekte Ein Objekt ist ein Gegenstand des Interesses Objekte können Dinge, Personen und Begriffe sein Objekte besitzen einen Zustand Objekte reagieren mit definiertem Verhalten auf ihre Umgebung Jedes Objekt besitzt eine Identität 4 Objekte Der Zustand eines Objekts wird beschrieben durch die Ausprägungen (Werte) seiner Eigenschaften (=Attribute) Attribute modellieren die (Software-interne) Datenstruktur Es werden nur diejenigen Eigenschaften eines Objekts, die für die Anwendung relevant sind, modelliert Attributwerte unterliegen Änderungen und repräsentieren die aktuellen (Software-internen) Daten 5 Objekte Beispiel: Kreis (mit Attributen Mittelpunkt und Radius) Mittelpunkt = (0,10) Radius = 30 Beispiel: Menge (mit Attribut Groesse und Elemente) Groesse = 1 Elemente = {5} Beispiel: Student (mit Attributen Name, Matrikelnummer,...) Name = „Huber“ Matrikelnummer = „1076894“ ... 6 Objekte Objekt-Identitäts-Prinzip Ein Objekt ist unabhängig von seinen konkreten Attributwerten von allen anderen Objekten eindeutig zu unterscheiden Objekte können also gleich, aber nicht identisch sein (zwei Objekte sind gleich, wenn sie dieselben Attribute haben und im selben Zustand sind) 7 Objekte Das Verhalten eines Objekts wird beschrieben durch eine Menge von Operationen Operationen ermöglichen den Zugriff auf die (die Verwaltung der) Daten durch Abfragen und Ändern von Attributwerten (Getter/Setter) Erzeugen von Objekten (Konstruktoren) Manipulieren von Beziehungen zwischen Objekten Berechnungen … 8 Objekte Das Verhalten eines Objekts wird beschrieben durch eine Menge von Operationen Operationen dienen wie Funktionen der funktionalen Abstraktion: Man legt zuerst nur fest, was berechnet werden soll In späteren Modellierungsschritten wird Top-Down festgelegt, wie die Berechnung erfolgt (dazu stehen andere Diagrammtypen zur Verfügung: z.B. Sequenzdiagramme, Aktivitätsdiagramme, Zustandsautomaten, …) 9 Objekte Beispiel: Kreis setPosition(neuerMittelpunkt) setRadius(neuerRadius) ... Beispiel: Menge istElement(einObjekt):boolean einfuegen(einObjekt) ... Beispiel: Student getName():Zeichenkette ... 10 Objekte Geheimnisprinzip: Abfragen oder Änderungen von Attributwerten sind nur mittels der Operationen möglich Also: kein direkter Zugriff auf Attributwerte Verwirklicht Prinzip der Einkapselung von Modulen Vorteile: Sicherstellen von Datenstruktur-Invarianten Datenstruktur mit weniger Aufwand änderbar 11 Klassen Objekte mit gleichen Attributen und Operationen werden zu Klassen zusammengefasst Eine Klasse ist ein Schema zur Spezifikation von Gemeinsamkeiten einer Menge von Objekten mit denselben Eigenschaften und demselben Verhalten Jedes Objekt gehört zu genau einer Klasse Klassen werden (grafisch) beschrieben durch einen Namen, eine Liste von Attributen und eine Liste von Operationen 12 Klassen Grafische Darstellung von Klassen Namensfeld <Klassenname> Attributliste <Attribut> <Attribut> ... Operationsliste <Operation> <Operation> ... Ein Klassenname ist ein Substantiv im Singular, beginnend mit einem Großbuchstaben [Attribute und Operationen: folgende Folien] 13 Klassen Beispiel: Kreis und Punkt Kreis Punkt position:Punkt radius:integer ... x:integer y:integer ... setPosition(in neuePosition:Punkt) getPosition():Punkt ... berechneFlaeche():double setX(in x:integer) getX():integer ... 14 Klassen Objekt-Klassen-Prinzip Ein Objekt ist ein zur Ausführungszeit des Programms vorhandenes Exemplar einer Klasse, allokiert Speicher, verhält sich entsprechend dem Schema der Klasse. Eine Klasse ist nur eine Vereinbarung, allokiert keinen Speicher Attributwerte sind individuell 15 Klassen Kohärenz-Prinzip Jede Klasse soll genau für einen (sachlogischen) Aspekt des Gesamtsystems verantwortlich sein Die zu einem Verantwortlichkeitsbereich gehörenden Eigenschaften und Operationen sollen nicht auf mehrere Klassen aufgeteilt sein Eine Klasse soll keine Eigenschaften und Operationen enthalten, die nicht zu dem Verantwortlichkeitsbereich gehören Zusammensetzung von Software nach dem Baukastenprinzip 16 Exkurs: Namensraum Ein Namensraum ist ein Bereich (eines Modells), in dem jedes Element einen eindeutigen Namen besitzen muss In unterschiedlichen Namensräumen kann der gleiche Name in unterschiedlicher Bedeutung verwendet werden 17 Attribute Attribute haben einen Namen sind von bestimmtem Typ können einen Anfangswert besitzen können Multiplizität haben (mehrere Komponenten) können Einschränkungen unterworfen sein (DatenstrukturInvarianten) 18 Attribute Namen Klassen definieren einen Namensraum für Attribut- und Operationsnamen Attributnamen müssen pro Klasse eindeutig sein Verschiedene Klassen können identische Attribute haben Zugriff mittels <Objektname>.<Attributname> Attributnamen beginnen mit einem Kleinbuchstaben und werden nach fachlichen Gesichtspunkten gewählt 19 Attribute Beispiel: Kreis und Rechteck Kreis Rechteck position radius ... position laenge breite ... ... ... 20 Attribute Attribut-Typen: Legen den Wertebereich eines Attributs fest (wie VariablenTypen in C) Dienen der möglichst präzisen Beschreibung der Daten aus fachlicher Sicht 21 Attribute Mögliche Attribut-Typen: Datentypen Primitive UML-Datentypen: Boolean, String, Integer, UnlimitedNatural oder selbst definiert Strukturierter Datentyp Aufzählungstyp Klassen 22 Attribute Datentypen vs. Klassen (Strukturierte) Datentypen können wie Klassen Attribute und Operationen besitzen Objekte eines Datentyps besitzen aber keine Identität (gleiche Attributwerte = gleiches Objekt) Existieren nur als Komponenten von Klassenobjekten Dienen der besseren Strukturierung Sind Objekte an sich für die Funktionalität interessant Wenn ja: Klassen, wenn nein: Datentyp 23 Attribute Grafische Darstellung von Datentypen ähnlich wie die von Klassen Unterschiede: Dem Namen wird bei primitiven Datentypen das Schlüsselwort <<primitive>> vorangestellt Dem Namen wird bei strukturierten Datentypen das Schlüsselwort <<datatype>> vorangestellt 24 Attribute Beispiel: Student und Adresse Student name:String adresse:Adresse ... ... <<datatype>> Adresse Ort:String Strasse:String ... ... Angabe von Typen nach dem Attributnamen, abgetrennt durch einen Doppelpunkt : 25 Attribute Anfangswert Der Anfangswert legt fest, welchen Wert ein neu erzeugtes Objekt für ein Attribut annimmt Der Anfangswert kann zur Laufzeit des Programms beliebig geändert werden Angabe nach dem Namen, abgetrennt durch ein Gleichheitszeichen = 26 Attribute Multiplizität Die Multiplizität legt die Anzahl der Werte (Komponenten) eines Attributs fest Angabe nach dem Namen in der Form [n..m] mindestens n und höchstens m Werte [0..m] Optionales Attribut, höchstens m Werte [n..*] beliebig viele Werte, mindestens n Werte [n] Genau n Werte [1] Voreinstellung 27 Attribute Multiplizität Attribute mit Multiplizität ungleich [1] kann man sich als Felder vorstellen 28 Attribute Einschränkungen Sind Aussagen über Attributwerte, die immer wahr sein müssen Geben Datenstruktur-Invarianten an Angabe nach dem Namen in geschweiften Klammern als prädikatenlogische Formel (oder auch umgangssprachlich) 29 Attribute Beispiel: Mengen ganzer Zahlen Menge groesse :Integer =0 elemente :Integer [0..*] {Anzahl der Werte von elemente = Wert von groesse} ... ... 30 Attribute Klassenattribute Haben nur einen Wert für alle Objekte einer Klasse, existieren also nur einmal pro Klasse Klassenattribute existieren auch dann, wenn es für eine Klasse (noch) keine Objekte gibt Zugriff mittels <Klassenname>.<Attributname> Angabe wir normale Attribute, allerdings unterstrichen 31 Attribute Beispiel: Student Student name:String adresse:Adresse anzahl :Integer =0 {anzahl>=0} ... ... Speicherung der Anzahl der erzeugten Objekte 32 Operationen Operationen haben einen Namen können Ein- und Ausgabeparameter haben können einen Rückgabetyp haben 33 Operationen Namen Klassen definieren einen Namensraum für Attribut- und Operationsnamen Operationsnamen müssen pro Klasse eindeutig sein Verschiedene Klassen können identische Operationen haben (die aber unterschiedlich implementiert werden) Zugriff mittels <Objektname>.<Operationsname> Operationsnamen beginnen mit einem Kleinbuchstaben und werden nach fachlichen Gesichtspunkten gewählt Der Operationsname soll ausdrücken, was die Operation leistet: Er enthält in der Regel ein Verb (was wird gemacht?) 34 Operationen Namen Operationsnamen können innerhalb einer Klasse mehrfach verwendet werden, wenn sie sich durch ihre Parameter unterscheiden (dieselbe Aufgabe mag von unterschiedlichen Parametern abhängen) Das nennt man Überladen von Operationen 35 Operationen Beispiel: Kreis und Rechteck Kreis Rechteck ... ... anzeigen() ... anzeigen() speichern() speichern(in dateiname:String) ... 36 Operationen Parameter Parameter definieren Ein- und Ausgabedaten von Operationen sich wiederholende Aufgaben, die sich nur durch unterschiedliche Werte oder Objekte unterscheiden, können verallgemeinert beschrieben werden Die sich unterscheidenden Informationen werden als Parameter formalisiert 37 Operationen Parameter Ein Parameter besteht aus der Angabe von Name Typ (optional) Multiplizität (optional) Anfangswert (optional) Richtung Name, Typ, Multiplizität und Anfangswert werden wie bei Attributen gewählt und angegeben 38 Operationen Parameter: Richtung Ein Parameter kann folgende Richtungen haben: in reiner Eingabeparameter Zugriff nur lesend out reiner Ausgabeparameter Wertzuweisung erst in der Operation inout Ein- und Ausgabeparameter Wertänderung in der Operation Angabe vor dem Namen 39 Operationen Rückgabetyp Gibt den Typ des Werts an, der zurückgegeben wird Angabe nach dem Namen mit vorangestelltem : Wird weggelassen, falls es keinen Rückgabewert gibt 40 Operationen Rückgabetyp Rückgabewert vs. Ausgabeparameter: Es kann maximal einen Rückgabewert geben Für Spezifikation der Änderung von Werten mehrerer Objekte durch eine Funktion braucht man Ausgabeparameter 41 Operationen Getter und Setter Um Daten zu lesen/zu schreiben benutzt man sog. getter- und setter-Operationen. Für jedes Attribut wird eine zugehörige getterund eine zugehörige setter-Operation eingeführt Eine setter-Operation setzt den Wert eines Attributs mittels eines Eingabeparameters neu Prototyp: set<Attributname>(in <neuerWert>) Eine getter-Operation liest den Wert eines Attributs und gibt diesen zurück Prototyp: get<Attributname>(): <Attributtyp> 42 Operationen Zugriff auf mehrwertige Attribute Für mehrwertige Attribute wird zusätzlich/ersatzweise ermöglicht, auf deren einzelne Werte zuzugreifen (hier ersetzt der setter alle Werte und der getter liest alle Werte auf einmal): add<Attributname>(in <zusätzlicherWert>) delete<Attributname>(in <veralteterWert>) get<Attributname>(in p:Integer):<Attributtyp> 43 Operationen Konstruktoren Konstruktoren sind Operationen zur Erzeugung und Initialisierung von Objekten Konstruktoren heißen immer wie die Klasse. Sonst Angabe wie bei Operationen Es kann mehrere Konstruktoren von Objekten einer Klasse mit unterschiedlichen Parameterlisten geben diese Konstruktoren führen also unterschiedliche Initialisierungen durch 44 Operationen Konstruktoren Konstruktoren initialisieren Attribute durch Zuweisung von Werten jedem Attribut mit Multiplizität [1..n] oder [1..*] sollte ein Wert zugewiesen werden (soll-Attribute) wird bei Attributen ohne Anfangswert durch Parameter übergeben oder es wird ein Standardwert genommen jedem Attribut mit Multiplizität [0..n] oder [0..*] kann ein Wert zugewiesen werden (kann-Attribute) 45 Operationen Klassenoperationen Klassenoperationen sind der jeweiligen Klasse zugeordnet und nicht auf ein einzelnes Objekt der Klasse anwendbar Zugriff mittels <Klassenname>.<Operationsname> Angabe wir normale Operationen, allerdings unterstrichen Für den Zugriff auf Klassenattribute Für Berechnungen, die sich auf mehrere Objekte einer Klasse beziehen 46 Operationen Beispiel: Student Student matrikelnummer:String Adresse:Adresse [0..1] anzahl :Integer =0 {anzahl>=0} ... Student(in matrikelnummer:String) Student(in matrikelnummer:String, in adresse:Adresse) sortieren() getAnzahl():Integer ... 47 Operationen Operationen vs. Funktionsaufrufe Operationen und Daten bilden eine (inhaltliche) Einheit Operationen lassen sich nur über das Objekt ansprechen Gleichnamige Operationen können für unterschiedliche Objekte verschieden implementiert sein 48 Wie findet man Klassen? Dokumentenanalyse: Formulare, Bedienungsanleitungen, Fragebögen, … Re-Engineering: Anleitungen, Hilfesystem, Bildschirmmasken, Benutzerdialoge, Funktionalität, … Nach Kategorien: Konkrete Dinge/Objekte, Personen, Rollen, Orte, Organisationen, Behälter, Dinge in einem Behälter, Kataloge, Verträge, Informationen über Aktionen, Ereignisse Pflichtenheft, Beschreibung der Systemidee in 5-20 Sätzen, … 49 Wie kombiniert man Objekte/Klassen? (Ausblick) Ein System besteht aus vielen Objekten/Klassen, die geeignet kombiniert werden müssen für eine erwünschte Funktionalität Nachrichtenaustauschprinzip Objekte sind eigenständige Einheiten, deren Zusammenarbeit mit Hilfe von Nachrichten bewerkstelligt wird, die sich Objekte untereinander zusenden Eine solche Nachricht ist ein Operationsaufruf Der Sender muss mit den eigenen Berechnungen auf die Bearbeitung der aufgerufenen Operation warten 50 Vorlesung Informatik II Universität Augsburg Sommersemester 2011 Prof. Dr. Robert Lorenz Lehrprofessur für Informatik 05. UML: Klassendiagramm 1 Klassendiagramm Im Klassendiagramm werden Klassen und ihre Beziehungen zueinander graphisch dargestellt Ein Klassendiagramm beschreibt das statische Datenmodell des Systems Ein Klassendiagramm definiert einen Namensraum für Klassennamen und Objektnamen Beziehungen können Assoziationen und Generalisierungen sein 2 Assoziationen Assoziationen beschreiben gleichartige Beziehungen zwischen Objekten Angestellter ist Vorgesetzter von Angestellter Professor betreut Diplomarbeit Menge besteht aus Elementen Verzeichnis ist ein Dateiobjekt 3 Assoziationen Assoziationen beschreiben gleichartige Beziehungen zwischen Objekten An einer Assoziation müssen mindestens zwei Objekte beteiligt sein Solche Beziehungen lassen sich in der Regel durch Verben beschreiben Werden grafisch durch Verbindungslinien zwischen den beteiligten Klassen dargestellt 4 Assoziationen Assoziationen weisen den beteiligten Klassen Multiplizitäten und Rollen zu können einen beschreibenden Namen besitzen können Navigierbarkeit besitzen können Einschränkungen unterliegen (Datenstruktur-Invarianten) können Eigenschaftswerte haben 5 Assoziationen Multiplizität Beschreibt Grenzen für die Anzahl von Objekten der anderen Klasse, die mit einem Objekt der betrachteten Klassen in Beziehung stehen können Wird an das Ende der Verbindunglinie bei der anderen Klasse in folgender Form angegeben: n..m mindestens n, höchstens m Objekte der anderen Klasse stehen mit einem Objekt der betrachteten Klasse in Beziehung Sonderfälle 0..m,n..*,1..m wie bei Attributen 6 Assoziationen Rolle Beschreibt die Funktion oder Aufgabe eines Objekts in einer Beziehung Rollen müssen zugewiesen werden, wenn zwischen bestimmten Klassen mehr als eine Assoziation besteht bei reflexiven Assoziationen (zwischen Objekten einer Klasse) Wird an das Ende der Verbindunglinie bei der betrachteten Klasse angegeben 7 Assoziationen Name Beschreibt die Art der Beziehung, in der Regel durch ein Verb. Bei binären Assoziationen: <Klassenname> <Assoziationsname> <Klassenname> sollte einen lesbaren Satz ergeben Der Name beschreibt eine Richtung der Beziehung Namen müssen zugewiesen werden, wenn zwischen bestimmten Klassen mehr als eine Assoziation besteht Wird in der Mitte der Verbindunglinie angegeben (mit Pfeil für die Lesrichtung bei binären Assoziationen) 8 Assoziationen Navigierbarkeit gibt an, ob Objekte einer betrachteten Klasse auf Objekte anderer an der Beziehung beteiligter Klassen zugreifen können Eine binäre Assoziation kann dabei uni-direktional sein (nur in eine Richtung navigierbar) bi-direktional sein (in beide Richtungen navigierbar) Brauchen Operationen Informationen über assoziierte Objekte? Ja: Navigierbarkeit einfügen Wird grafisch durch Pfeilspitzen in Richtung der Navigierbarkeit an Verbindungslinie angegeben 9 Assoziationen Navigierbarkeit In Java gibt es keine Assoziationen Stattdessen werden sog. Referenzattribute benutzt Aufbau einer Objektbeziehung: Dieses Referenzattribut wird mit einem Objekt initialisiert Auf die Daten dieses assoziierten Objekts wird über das Referenzattribut zugegriffen Achtung: Im UML-Modell tauchen diese Referenzattribute NICHT auf 10 Assoziationen Assoziationen: Grafische Darstellung <Klassenname> <Klassenname> n..m *..* <rollenname> <rollenname> ← <assoziationsname> <Klassenname> <Klassenname> 11 Assoziationen Beispiel: Angestellter ist Vorgesetzter von Angestellter Angestellter Vorgesetzter 1..1 Mitarbeiter 1..* ist Vorgesetzter von → Ein Vorgesetzter hat 1 oder mehrere Mitarbeiter Jeder Mitarbeiter hat genau einen Vorgesetzten Im System kennt der Vorgesetzte seine Mitarbeiter, aber nicht umgekehrt Muss zu fachlichen Gegebenheiten passen 12 Assoziationen Beispiel: Professor betreut Diplomarbeit Professor 1..1 betreuer betreut → 0..* diplomarbeiten Diplomarbeit Ein Professor betreut 0 oder mehrere Diplomarbeiten Eine Diplomarbeit hat genau einen Professor als Betreuer Der Professor kennt die von ihm betreuten Diplomarbeiten, umgekehrt nicht Muss zu fachlichen Gegebenheiten passen 13 Assoziationen Verwaltungsoperationen Um Objektbeziehungen herzustellen, zu löschen oder abzufragen benutzt man sog. link-, unLink- und getLink-Operationen. Für jede bekannte Beziehung (Navigierbarkeit!) werden standardmäßig solche Operationen eingeführt 14 Assoziationen Verwaltungsoperationen: einwertige Beziehungen Eine link-Operation stellt eine Beziehung zu einem existierenden Objekt her (es wird kein Objekt erzeugt!) Eine unLink-Operation löst die Beziehung zu existierendem Objekt auf (es wird kein Objekt gelöscht!) Eine getLink-Operation gibt das in Beziehung stehende Objekt zurück <Klasse1> ... link<rolle>(in k:<Klasse2>) unlink<rolle>() getLink<rolle>():<Klasse2> <n..1> <rolle> <Klasse2> 15 Assoziationen Verwaltungsoperationen: mehrwertige Beziehungen Eine link-Operation stellt eine Beziehung zu einem existierenden Objekt her (es wird kein Objekt erzeugt!) Eine unLink-Operation löst Beziehung zu einem existierenden Objekt auf (es wird kein Objekt gelöscht!) Eine getLink-Operation gibt ein in Beziehung stehendes Objekt zurück <Klasse1> ... link<rolle>(in k:<Klasse2>) unlink<rolle>(in k:<Klasse2>) getLink<rolle>(in pos:Integer): <Klasse2> <n..*> <rolle> <Klasse2> 16 Assoziationen Verwaltungsoperationen: bi-direktionale Assoziationen Entsprechende link-, unlink- und getLink-Operationen werden in beide Klassen eingetragen Implementierung: Es muss jeweils auf die wechselseitig konsistente Verwaltung geachtet werden Jede link-Operation sorgt für das Herstellen einer Objektbeziehung in beide Richtungen! Jede unLink-Operation sorgt für das Löschen einer Objektbeziehung in beide Richtungen! 17 Assoziationen Beispiel: Angestellte, Mitarbeiter und Vorgesetzte Angestellter ... linkMitarbeiter(in a: Angestellter) unLinkMitarbeiter(in a: Angestellter) getLinkMitarbeiter(in n:Integer):Angestellter Vorgesetzter Mitarbeiter 1..* 1..1 ist Vorgesetzter von → 18 Assoziationen Ist das Modell korrekt? Es gibt nie das korrekte oder das beste Modell, sondern immer mehrere verschiedene mögliche Alternativen, einen Sachverhalt zu modellieren Oft muss eine Trade-Off zwischen verschiedenen Kriterien gefunden werden: Beispiel: Weniger Navigierbarkeit einfacher zu implementieren, aber u.U. eingeschränkte Funktionalität Wichtig: man muss seinen Modellierungsvorschlag begründen können 19 Assoziationen Assoziationsklassen Sind Assoziationen mit Attributen, Operationen und Assoziationen zu anderen Klassen Assoziationsklassen können in Assoziationen und eine normale Klasse aufgelöst werden (beachte Anpassung der Multiplizitäten und Navigierbarkeiten) Grafisch wie Klassen, durch gestrichelte Linie mit Assoziationsverbindungslinie verbunden 20 Assoziationen Assoziationsklasse: Grafische Darstellung <Klassenname> <Klassenname> <Assklassenname> 21 Assoziationen Beispiel: Student leiht Buch aus Student leiht aus → 0..1 0..* Buch Ausleihe datum zeitraum Student Ausleihe 1..1 0..* datum zeitraum 1..1 0..1 Buch 22 Aggregationen Eine Assoziation zwischen zwei Klassen ist eine Aggregation, wenn zwischen den Objekten der beteiligten Klassen eine Rangordnung im Sinne von „ist Teil von“ bzw. „besteht aus“ gilt. Eine der Klassen ist das Ganze, die andere Klasse seine Teile Aggregationen dürfen keine Zyklen bilden Objekte können Teile von mehreren Ganzen sein, existieren also unabhängig vom Ganzen Navigierbarkeit: Das Ganze kennt seine Teile Grafisch dargestellt durch nicht ausgefüllte Raute am Ende der Verbindungslinie zum Ganzen 23 Aggregationen Verwaltungsoperationen Dienen der Verwaltung der Teile durch das Ganze Haben andere intuitivere Namen: insert-Operation entspricht link-Operation remove-Operation entspricht unLink-Operation get-Operation entspricht getLink-Operation 24 Aggregationen Aggregation: grafische Darstellung <Klassenname> besteht aus → ganzes teile <Klassenname> 25 Aggregationen Beispiel: Menge aus Objekten einer Klasse Menge ... insertElemente(in k:<Klasse>) removeElemente(in k:<Klasse>) getElemente(in pos:Integer):<Klasse> 0..* elemente 0..* <Klasse> 26 Kompositionen Eine Aggregation ist eine Komposition, wenn ein Objekt nur Teil eines Ganzen sein kann Wird das Ganze gelöscht, werden automatisch auch seine Teile gelöscht Grafisch dargestellt durch ausgefüllte Raute am Ende der Verbindungslinie zum Ganzen Verwaltungsoperationen haben andere intuitivere Namen: add-Operation entspricht link-Operation delete-Operation entspricht unLink-Operation get-Operation entspricht getLink-Operation 27 Kompositionen Komposition: grafische Darstellung <Klassenname> 0..1 ganzes teile <Klassenname> 28 Kompositionen Beispiel: Verzeichnis besteht aus Dateiobjekten Verzeichnis ... addElemente(in d:<Dateiobjekt>) deleteElemente(in d:<Dateiobjekt>) getElemente(in p:Integer):<Dateiobjekt> 0..1 elemente 0..* Dateiobjekt Irgendwas passt hier aber noch nicht: Verzeichnisse sind doch auch Dateiobjekte!? Modell (noch) unvollständig/ungenau (Verbesserung später) 29 Mehrwertige Assoziationen Mehrwertige Assoziationen beschreiben Beziehungen zwischen Objekten von drei oder mehr verschiedenen Klassen <Klassenname> <Klassenname> <Klassenname> Auch hier ist die Angabe von Rollen und Assoziationsnamen (ohne Richtung) möglich Navigierbarkeit und Multiplizitäten nur eingeschränkt modellierbar Braucht man selten 30 Generalisierung Eine Assoziation zwischen zwei Klassen ist eine Generalisierung, wenn zwischen den Objekten der beteiligten Klassen eine Rangordnung im Sinne von „ist ein“ gilt Generalisierungen dürfen keine Zyklen bilden Generalisierungen erlauben keine Angabe von Navigierbarkeit, Rollen, Multiplizitäten und Namen (diese Eigenschaften sind alle implizit klar) 31 Generalisierung Jedes Objekt der sog. Unterklasse ist ein Objekt der sog. Oberklasse Eine Generalisierung beschreibt die Beziehung zwischen einer (allgemeinen) Klasse (Oberklasse) und einer Spezialisierung dieser Klasse (Unterklasse) Grafisch dargestellt durch eine geschlossene, nicht ausgefüllt Pfeilspitze am Ende der Verbindungslinie zur Oberklasse 32 Generalisierung Jedes Objekt der sog. Unterklasse ist ein Objekt der sog. Oberklasse Ein Objekt der Unterklasse hat alle Attribute, Operationen und Assoziationen der Oberklasse und enthält zusätzliche Informationen in Form von zusätzlichen Attributen, Operationen und Assoziationen Attribute, Operationen und Assoziationen der Oberklasse werden nicht noch einmal für die Unterklasse angegeben 33 Generalisierung Generalisierung: grafische Darstellung <Oberklassenname> <Unterklassenname> <Unterklassenname> 34 Generalisierung Beispiel: Dateien und Verzeichnisse sind Dateiobjekte Dateiobjekt Datei 0..* Verzeichnis Auch hier passt eigentlich noch was nicht: Wird man jemals ein Objekt vom Typ Dateiobjekt erzeugen, das keine Datei oder Verzeichnis ist? Nein! Modellierung als sog. Abstrakte Klasse (später) 35 Generalisierung Beispiel: Dateien und Verzeichnisse sind Dateiobjekte Dateiobjekt 0..* name erstelldatum Datei Verzeichnis groesse freigabe Gemeinsame und spezielle Attribute 36 Generalisierung Beispiel: Dateien und Verzeichnisse sind Dateiobjekte Dateiobjekt 0..* ... kopieren() Datei Verzeichnis ... ... speichern() freigeben() Gemeinsame und spezielle Operationen 37 Generalisierung Vererbungsprinzip Die Oberklasse vererbt ihre Attribute, Operationen und Beziehungen an die Unterklasse Ein Objekt der Unterklasse besitzt alle Attribute der Oberklasse Alle Operationen der Oberklasse können über Objekte der Unterklasse aufgerufen werden Ein Objekt der Unterklasse ist an allen Assoziationen der Oberklasse beteiligt Die Objekte einer Klasse kennen alle Oberklassen (aber nicht die Unterklassen!) 38 Generalisierung Substitutionsprinzip Objekte von Unterklassen können jederzeit als ein Objekt einer Oberklassen verwendet werden Entspricht einer Typausweitung 39 Generalisierung Objekt-Verantwortlichkeitsprinzip Jede Klasse definiert einen Verantwortlichkeitsbereich. Attribute und Operationen werden entsprechend dem Verantwortlichkeitsbereich einer möglichst speziellen Klasse in einer Vererbungshierarchie zugeordnet 40 Generalisierung Top-Down-Entwurf einer Vererbungshierarchie: Bildung von Unterklassen durch Addition von Attributen, Operationen und Assoziationen zu einer Klasse Beispiel: Ein Tutor ist eine Spezialisierung eines Studenten 41 Generalisierung Bottom-Up-Entwurf einer Vererbungshierarchie: Bildung von Oberklassen durch Zusammenfassen gemeinsamer Merkmale mehrerer Klassen Oft sind das abstrakte Klassen, die nur der Modellierung gemeinsamer Informationen von spezialisierten Klassen dienen, von denen aber keine Objekte erzeugt werden 42 Generalisierung Prinzip abstrakter Klassen Klassen, von denen keine Objekte erzeugt werden können oder sollen, heißen abstrakte Klassen Eine abstrakte Klasse stellt gemeinsame Eigenschaften und Operationen für ihre Unterklassen zur Verfügung Darstellung wie Klassen, zusätzliche Schlüsselwort abstract 43 Generalisierung Prinzip abstrakter Klassen Klassen, von denen keine Objekte erzeugt werden können oder sollen, heißen abstrakte Klassen Abstrakte Klassen können konkrete Operationen enthalten Abstrakte Klassen enthalten in der Regel abstrakte Operationen, die sie nicht implementieren Unterklassen müssen abstrakte Operationen implementieren Abstrakte Operationen haben in verschiedenen Unterklassen i.d.R. unterschiedliche Implementierung 44 Generalisierung Prinzip abstrakter Operationen Werden in der betrachteten Klasse nicht implementiert, sondern nur vereinbart durch Angabe des Prototypen (Signatur) Durch abstrakte Operationen werden gemeinsame Signaturen für Unterklassen definiert. In der Implementierung müssen die Unterklassen die abstrakte Operation durch konkrete Operationen überschreiben Klassen mit abstrakten Operationen müssen auch abstrakt sein 45 Generalisierung Beispiel: Dateien und Verzeichnisse sind Dateiobjekte <<abstract>> Dateiobjekt ... getName() kopieren() {abstract} Datei ... kopieren() 0..* Verzeichnis ... kopieren() Implementierung abstrakter Operationen in Unterklassen 46 Generalisierung Polymorphismus: Unterklassen können Operationen von Oberklassen überschreiben (redefinieren) und unterschiedlich implementieren Derselbe Operationsaufruf für Objekte verschiedener Klassen einer Vererbungshierarchie führt zur Ausführung unterschiedlicher Operationen (Aufruf für jedes Dateiobjekt o: o.kopieren()) Der Aufrufer muss die genaue Klasse eines Empfängerobjekts (Verzeichnis oder Datei) nicht kennen, sondern nur wissen, dass die Operation zur Verfügung steht (ist ein Dateiobjekt) 47 Generalisierung Spätes Binden: Beim Übersetzen des Programms muss für ein Objekt der Oberklasse noch nicht bekannt ist, zu welcher Unterklasse es gehört. Erst zur Laufzeit wird die Operation an das Objekt gebunden. Einheitlicher Aufruf für potentiell unterschiedliche Objekte Dadurch werden Mehrfachauswahlen vermieden Beispiel: for all o in list: o.kopieren() 48 Generalisierung Überschreiben vs. Überladen Überladen: Eine Operation kann innerhalb einer Klasse öfter mit verschiedenen Signaturen vorkommen (Operation println() der Klasse PrintStream) Überschreiben: Eine Operation einer Oberklasse kann von einer Operation einer Unterklasse mit gleicher Signatur überschrieben werden 49 Generalisierung Überschreiben von Attributen Unterklassen können Attribute von Oberklassen durch Namensgleichheit verbergen In diesem Fall sind beide Attribute vorhanden und das geerbte Attribut ist in der Unterklasse nicht sichtbar Programmiersprachen stellen Notationen für den Zugriff auf verborgene Attribute bereit 50 Generalisierung Mehrfachvererbung Grundsätzlich können Objekte von mehreren Klassen erben (mehrere Oberklassen haben) Da dies in Java nicht adäquat abgebildet werden kann, wollen wir in dieser Vorlesung darauf verzichten Vereinbarung: Jede Klasse ist Unterklasse von höchstens einer Oberklasse 51 Generalisierung Vorteile: Einfache Modellierung neuer spezialisierter Klassen unter Verwendung existierender Klassen Leichte Durchführbarkeit von Änderungen (Änderungen an einer Oberklasse sind auch für alle Unterklassen wirksam) Nachteile: Zur Kenntnis einer Klasse muss man auch alle ihre Oberklassen kennen Bei Hinzufügen/Änderung einer Oberklasse müssen u.U. auch alle Unterklassen verändert werden 52 Schnittstellen Eine Schnittstelle ist eine Sammlung von abstrakten Operationen und konstanten Klassenattributen Schnittstellen dürfen keine konkreten Operationen haben Durch abstrakte Operationen werden gemeinsame Signaturen für Klassen zur Verfügung gestellt. Angabe wie Klassen, zusätzlich mit Schlüsselwort interface Operationen werden nicht extra als abstract gekennzeichnet 53 Schnittstellen Klassen können Schnittstellen implementieren Dazu implementieren sie alle spezifizierten Operationen konkret und können die konstanten Klassenattribute benutzen Verschiedene Klassen können dieselbe Schnittstelle auf unterschiedliche Weise implementieren Eine Klasse kann mehrere Schnittstellen implementieren (Ersatz für Mehrfachvererbung) Zwischen Schnittstellen gibt es Generalisierungsbeziehungen Angabe durch gestrichelten Generalisierungspfeil 54 Schnittstellen Schnittstellen-Prinzip In der Schnittstelle spezifizierte Operationen können für jede implementierende Klasse auf dieselbe Weise aufgerufen werden (Schnittstellen können als Datentyp benutzt werden) 55 Schnittstellen Grafische Darstellung <<interface>> <Schnittstellenname> <Klassenname> <Klassenname> 56 Schnittstellen Beispiel: Durchlaufen von dynamischen Feldern (Klassenbibliothek: Iteratormuster) <<interface>> Iterable<E> iterator():Iterator<E> Vector ArrayList <<interface>> Iterator<E> hasNext():boolean next():<E> remove() ... 57 Sichtbarkeiten Für Klassen, Attribute, Operationen und Assoziationen kann man Sichtbarkeiten spezifizieren, die deren Benutzbarkeit durch andere Modellelemente einschränkt + überall sichtbar (public) - innerhalb des eigenen Namensraums sichtbar (private) # innerhalb aller Spezialisierungen des eigenen Namensraums sichtbar (protected) ~ innerhalb des eigenen Pakets sichtbar (package) Wird vor dem Namen angegeben 58 Sichtbarkeiten Für Klassen (In welchen anderen Klassen stehen Objekte der Klasse zur Verfügung): + überall sichtbar - innerhalb des eigenen Pakets # nicht benutzbar ~ nicht benutzbar 59 Sichtbarkeiten Für Attribute (Objekte welcher Klassen können auf den Attributwert ohne Operation zugreifen): + überall sichtbar - sichtbar in der Klasse # sichtbar innerhalb der Klasse und allen Unterklassen ~ sichtbar im Paket 60 Sichtbarkeiten Für Operationen (Objekte welcher Klassen können die Operation aufrufen): + überall sichtbar - sichtbar in der Klasse # sichtbar innerhalb der Klasse und allen Unterklassen ~ sichtbar im Paket 61 Sichtbarkeiten Für Assoziationen: Angabe für Rollen + überall sichtbar - sichtbar in der Klasse # sichtbar innerhalb der Klasse und allen Unterklassen ~ sichtbar im Paket 62 Sichtbarkeiten Geheimnisprinzip Als Sichtbarkeitsstandard für Attribute und Assoziationen sollte immer wenn möglich private gewählt werden Bei Operationen: Kann man durch Aufruf Datenstrukturinvariante zerstören? Wird die Aufrufbarkeit von außerhalb benötigt? Vorteile: Konsistenzprüfung möglich, bessere Modifizierbarkeit und Wartbarkeit, Schutz von Datenstruktur-Invarianten Nachteile: Zusätzliche Operationen 63 Sichtbarkeiten Beispiel: Menge von Objekten einer Klasse implementiert als einfach verkettete Liste 0..1 -next + Knoten 1..1 0..1 -start + Liste -size:Integer =0 -wert + <Klasse> 64 Sichtbarkeiten Beispiel: Menge von Objekten einer Klasse implementiert als einfach verkettete Liste: Geheimnisprinzip? + Liste + Knoten + + + + + + + + Knoten() Knoten(wert:<Klasse>) linkWert(k:<Klasse>) unLinkWert() getLinkWert():<Klasse> linkNext(k:Knoten) unLinkNext() getLinkNext():Knoten - size:Integer =0 -start 0..1 + Liste() + getSize():Integer - setSize(n:Integer) - linkStart(k:Knoten) - unLinkStart() - getLinkStart():Knoten + insert(o:<Klasse>) ... 65 Containerklassen Containerklassen werden zur Verwaltung von Objekten anderer Klassen eingesetzt Eine Containerklasse enthält nur ein Objekt, das Container genannt wird (Beispiel: Listen, dynamische Felder, …). Es enthält die zu verwaltenden Objekte. Es werden Standardoperationen zum Zugriff auf verwaltete Objekte bereitgestellt (Einfügen, Löschen, Suchen) Beziehung des Containers zu der Klasse der verwalteten Objekte ist eine Komposition 66 Containerklassen Containerklassen werden durch das sog. Singleton-Muster modelliert Das Singletonmuster stellt sicher, dass höchstens ein Objekt einer Klasse erzeugt werden kann: 1. Konstruktor ist private 2. Verwaltung des Objekts durch ein privates Klassenattribut (unique) [zeigt am Anfang auf null] 3. Zugriff/Erzeugung über öffentliche Klassenoperation (instance), die das Objekt zurückgibt [überprüft, ob Objekt existiert und erzeugt es, falls nicht] 67 Containerklassen Grafische Darstellung + <Containerklasse> - unique :<Containerklasse> =null - <Containerklasse>() + instance(): <Containerklasse> 1..1 - alleObjekte 0..* + <Klasse> 68 Containerklassen Beispiel: Professoren + ProfessorenContainer - unique :ProfessorenContainer =null + + + + ProfessorenContainer() instance(): ProfessorenContainer addProfessor(in p:Professor) deleteProfessor(in p:Professor) getProfessor(in p:Integer):Professor 1..1 - alleProfessoren 0..* + Professor 69 Containerklassen Containerklassen erhalten die Klassenattribute und –operationen der verwalteten Klasse als Objektattribute und -operationen <Containerklasse> <Klasse> <Attribut> <Attribut> <Operation> 1..1 <Operation>() - alleObjekte 0..* <Klasse> 70 Containerklassen Beispiel: Klassenattribute und –operationen <Containerklasse> <Klasse> anzahl anzahl getAnzahl() 1..1 getAnzahl() - alleObjekte 0..* <Klasse> 71 Muster Muster sind generische Lösungen für wiederkehrende Entwurfsprobleme Erhöhen die Standardisierung und damit die Qualität und Wartbarkeit des Entwurfs und der Software Muster werden durch Klassendiagramme beschrieben Beispiel: Singletonmuster, falls es höchstens ein Objekt einer Klasse geben soll In der Praxis: Vielzahl von Mustern In dieser Vorlesung: 2-3 exemplarische Muster 72 Vorlesung Informatik II Universität Augsburg Sommersemester 2011 Prof. Dr. Robert Lorenz Lehrprofessur für Informatik 06. Java: Von UML nach Java 1 Inhalt Für die meisten Elemente und Konzepte eines Klassendiagramms gibt es Entsprechungen in Java Wir werden jetzt die Syntax dieser Entsprechungen lernen Angenehmerweise bleibt die Semantik erhalten, wir haben bei der UML-Modellierung also schon die halbe Programmierarbeit erledigt Manchmal hat man allerdings Implementierungsalternativen Wir beginnen mit einigen API-Grundlagen. 2 Operator instanceof Erlaubt die Überprüfung, ob ein Objekt von einer bestimmten Klasse ist in der folgenden Form <Objekt> instanceof <Klasse> Wert dieses Ausdrucks ist vom Typ boolean 3 Klasse Object Jede Klasse erbt (ist eine Spezilisierung) von der Klasse Object: Konsequenzen: Ein Objekt jeder beliebigen Klasse kann an eine Variable der Klasse Object zugewiesen werden Die Methoden, die in der Klasse Object definiert sind, stehen in jeder Klasse zur Verfügung Wichtige Methoden der Klasse Object: public boolean equals(Object obj) public String toString() 4 Klasse Object public boolean equals(Object obj) Definiert die Gleichheit zweier Objekte Voreinstellung: Identität (Zeiger auf dasselbe Objekt) Die Klasse String überschreibt diese Methode schon, s.d. zwei Zeichenketten tatsächlich auf gleichen Inhalt überprüft werden 5 Klasse Object public boolean equals(Object obj) Diese Methode kann und sollte von jeder Klasse überschrieben werden was Gleichheit bedeutet, legt der Programmierer der Klasse fest Andere Bibliotheksoperationen benutzen equals (z.B. die Operation contains von Containerklassen) 6 Klasse Object public boolean equals(Object obj) Beispiel: Zwei Studenten sind gleich, wenn sie dieselbe Matrikelnummer haben class Student { private String matnummer; public boolean equals(Object o){ if (o instanceof Student){ Student s = (Student) o; return (matnummer == s.matnummer); } return false; }... 7 Klasse Object public String toString() Definiert die textuelle Darstellung eines Objekts (als eine Zeichenkette) Jede Klasse sollte diese Methode überschreiben das Ergebnis sollte möglichst informativ und kompakt den wesentlichen Inhalt des Objekts wiedergeben Diese Methode wird implizit aufgerufen, wenn ein Objekt textuell dargestellt werden muss (z.B. bei Aufruf von println()) 8 Klasse Object public String toString() Beispiel: Für Studenten wird Name und Matrikenummer ausgegeben class Student { ... public String toString(){ return “Matrikelnummer: “ + matnummer + “\n Name: “ + name; } ... 9 Containerklassen Grundsätzliche Typen: Listen: für beliebige Objekte in fester Reihenfolge mit wahlfreiem und sequentiellem Zugriff Mengen: für beliebige Objekte, keine Dubletten, Mengenoperationen Abbildungen: Menge von Paaren, eines davon dublettenfreier Schlüssel für den Zugriff auf das zugeordnete Objekt, kann man sich als Tabelle mit zwei Spalten (Schlüssel + Objekt) vorstellen 10 Containerklassen Beispielklassen: Vector Liste Dynamisches Feld, schneller Zugriff, langsames Einfügen / Löschen, für Lesen und kleine Listen LinkedList Liste Doppelt verkettete Liste, langsamer Zugriff, schnelles Einfügen / Löschen, bei vielen Änderungen, für große Listen 11 Containerklassen Beispielklassen: HashSet Menge Iterationsreihenfolge ist ungeordnet und nicht reproduzierbar Hashtable Abbildung 12 Klasse Vector Exemplarisch besprechen wir die Klasse Vector<T>: repräsentiert ein dynamisches Feld von Objekten Elemente von primitiven Datentypen können nicht verwaltet werden (hier helfen die Hüllklassen) Zugriff auf Elemente wie bei Feldern T ist der Datentyp der Elemente (Angabe ist optional). Ohne Angabe von T Verwaltung von beliebigen Objekten 13 Klasse Vector Einige Operationen der typisierten Version Vector<T>: void addElement(T obj) hängt obj als letztes Element an void insertElementAt(T obj, int index) fügt obj an Position index ein und verschiebt andere Elemente T elementAt(int index) liefert das Element an Stelle index Alternative: T get(int index) void setElementAt(T obj, int index) ersetzt das Element an Position index durch obj 14 Klasse Vector Einige Operationen der typisierten Version Vector<T>: int indexOf(T elem) liefert den Index des ersten Elements e mit e.equals(elem) boolean removeElement(T obj) entfernt das erste Auftreten von obj int size() liefert die Anzahl der aktuellen verwalteten Objekte Bei der nicht typisierten Version Vector werden ggf. Objekte vom Typ Object zurückgegeben Typcast notwendig! 15 Sichtbarkeiten + entspricht public - entspricht private # entspricht protected ~ entspricht package 16 Klassen Angabe von Klassen in folgender Form: <Sichtbarkeit> [abstract] class <Klassenname> { <Attributeliste> <Konstruktorenliste> <Operationsliste> } UML-Klassen und strukturierten UML-Datentypen werden als Java-Klassen implementiert Angabe von abstract für abstrakte Klassen 17 Attribute Angabe von Attributen in folgender Form: <Sichtbarkeit> [static] <Datentyp> <Name> [=<Wert>] Angabe von static für Klassenattribute Angabe von =<Wert> für Anfangswerte <Datentyp> abhängig von Multiplizität: ?..1 <Datentyp> entspricht UML-Datentyp ?..m <Datentyp> entspricht UML-Datentyp-Feld (m>1) ?..* <Datentyp> entspricht einer Java-Containerklasse 18 Attribute Möglichkeiten der Initialisierung von Attributen: Explizit in der Deklaration Explizit im Konstruktor Implizit durch voreingestellten Wert Initialisierung von Klassenattributen Explizit in der Deklaration In separatem Block static { ... } 19 Objekte Auswertung von Objekten: Objekte primitiven Typs werden als Wert der Speicherstelle ausgewertet Objekte eines Referenztyps werden als Zeiger auf die Speicherstelle ausgewertet Ein Ausdruck der Form <objekt>.<attribut> wird als Wert des Attributs ausgewertet (automatische Dereferenzierung) 20 Konstruktoren Angabe von Konstruktoren in folgender Form: <Sichtbarkeit> <Klassenname>(<Parameter>){<Rumpf>} UML-Konstruktoren werden Java-Konstruktoren Konstruktoren können überladen werden Fehlt ein Konstruktor, so erzeugt der Compiler automatisch einen leeren Konstruktor public <Klassenname>(){} (ohne Parameter, d.h. ohne benutzerdefinierte Initialisierungen) Prototyp wird wie bei normalen Java-Operationen angegeben 21 Konstruktoren Das Schlüsselwort this: Mit this(<Werte>) kann in einem Konstruktor auf einen anderen Konstruktor zugegriffen werden Mit this.<attribut> kann auf überschriebene Attribute zugegriffen werden this kann in Operationsrümpfen als Referenz auf das aufrufende Objekt benutzt werden (Beispiel später) 22 Konstruktoren Aufruf von Konstruktoren Aufruf durch Ausdruck new <Klassenname>(<Werte>) Erzeugung eines Objekts Ausdruck wird als Zeiger auf dieses Objekt ausgewertet Verwendung in beliebigen Ausdrücken und auch als Eingabeparameter von Operationen 23 Konstruktoren Implementierung von Konstruktoren class <Klasse>{ private <Typ> <Attribut>; ... public p <Klasse>(<Typ> <Attribut>){ this.<Attribut>=<Attribut>; } public p <Klasse>(<Typ> <Attribut>,...){ this(<Attribut>); ... } } 24 Operationen Angabe von Operationen in folgender Form: <Sichtbarkeit>[static][abstract]<Rückgabetyp><Name>(<Parameter>){ <Rumpf> } UML-Operationen werden Java-Operationen (alle Verwaltungsoperationen für Attribute und Assoziationen usw.) Gibt es keinen UML-Rückgabetypwert, so ist der JavaRückgabetyp void Angabe von abstract bei abstrakten Operationen Abstrakte Operationen haben keinen Rumpf Angabe von static bei Klassenoperationen 25 Operationen Im Operations-Rumpf Werte primitiven Datentyps werden nach dem Call-by-ValuePrinzip übergeben Objekte eines Referenztyps werden nach dem Call-by-ReferencePrinzip übergeben Übergabe des Rückgabewerts (falls Rückgabetyp nicht void) mit return <Wert> Gleiche Verwendung von this wie in Konstruktoren 26 Operationen Aufruf von Operationen Aufruf von normalen Objekt-Operationen durch Ausdruck <objekt>.<operation>(<Werte>) (vorher muss das Objekt <objekt> deklariert und erzeugt werden) Aufruf von Klassenoperationen durch Ausdruck <klassenname>.<operation>(<Werte>) Ausdruck wird als Rückgabewert der Operation ausgewertet Verwendung in beliebigen Ausdrücken und auch als Eingabeparameter von Operationen 27 Operationen Implementierung von Gettern und Settern Einfachste Form: class <Klasse>{ private <Typ> <Attribut>; ... public p <Typ> get<Attribut>(){ return <Attribut>; } public p void set<Attribut>(<Typ> <Attribut>){ this.<Attribut>=<Attribut>; } } 28 Operationen Implementierung von Gettern und Settern Zusätzliche Fehlerbehandlung: Überprüfung Dateninvarianten bei Settern (ungültige Werte) Beispiel: Namen beginnen mit Großbuchstaben und haben eine Länge zwischen 3 und 20 Buchstaben Kontrolle, ob Wert vorhanden (bei optionalen Attributen) bei Gettern 29 Operationen Implementierung von Gettern und Settern Verhalten bei Auftreten eines Fehlers: Aktion nicht ausführen Anzeige über Rückgabewert (Fehlerbehandlung durch den Aufrufer) oder Fehlermeldung public boolean setName(String name){ if ((name.length()>2)&&(name.length()<21)){ return false;} this.name = name; return true; } Später: Ausnahmebehandlung in Java mit Ausnahmeklassen 30 Operationen Implementierung bei mehrwertigen Attribute (einfachste Form): class <Klasse>{ private Vector<T> <Attribut>; public p <T> get<Attribut>(int pos){ return <Attribut>.elementAt(pos); } public p void add<Attribut>(<T> <Wert>){ <Attribut>.addElement(<Wert>); } public p void remove<Attribut>(<T> <Wert>){ <Attribut>.removeElement(<Wert>); } } 31 Operationen Implementierung der Verwaltung mehrwertiger Attribute: Zusätzliche Fehlerbehandlung: Überprüfung Dateninvarianten bei add- und delete-Operation Beispiel: Schon vorhandenes Objekt (contains, equals) hinzufügen Fehlerkontrolle der benutzten Vector-Operationen Klasse Vector: public boolean removeElement(Object obj) gibt false zurück, falls Objekt nicht vorhanden, sonst true [Verhalten bei Auftreten eines Fehlers analog zu gettern/settern] 32 Operationen Implementierung der Verwaltung von Objektbeziehungen: später 33 Spezialisierung Angabe von Spezialisierungen in folgender Form: class <Klasse1> extends <Klasse2>{<Rumpf>} <Klasse2> ist dann Oberklasse von <Klasse1> In Unterklasse können geerbte Attribute und Operationen der Oberklasse benutzt werden Ausnahme: Konstruktoren werden nicht vererbt Mit super(<Werte>) Aufruf Konstruktor der Oberklasse (nur als erste Anweisung erlaubt) (wird auch implizit durch Compiler mit leerem Konstruktor erledigt) 34 Spezialisierung Implementierung: Benutzung von super public class <Klasse2>{ private <Typ2> <Attribut2>; public <Klasse2>(<Typ2> <Attribut2>){...} } public class <Klasse1> extends <Klasse2>{ private <Typ1> <Attribut1>; public <Klasse1>(<Typ1> <Attribut1>,<Typ2> <Attribut2>){ super(<Attribut2>); ... } } 35 Spezialisierung Implementierung: Polymorphismus public class <Klasse1> extends <Klasse2>{ ... } class meinProgramm{ public static void main(String args[]){ <Klasse2> o = new <Klasse1>(...); ... o stehen genau die <Klasse2>-Methoden zur Verfügung Überschreibt <Klasse1> eine <Klasse2>-Methode, wird aber die <Klasse1>-Version benutzt 36 Uni-direktionale Assoziationen Angabe von einwertigen Assoziationen in folgender Form: <Klasse1> ?..1 - <rolle> <Klasse2> public class <Klasse1>{ private <Klasse2> <rolle>; ... } Beziehung über den Rollennamen als Attribut einbinden in Richtung der Navigierbarkeit Zugriff über öffentliche Verwaltungsoperationen wie im Klassendiagramm spezifiziert 37 Uni-direktionale Assoziationen Verwaltungeoperationen für einwertige Assoziationen <Klasse1> ?..1 - <rolle> <Klasse2> public class <Klasse1>{ private <Klasse2> <rolle>; public void link<rolle>(<Klasse2> k){ <rolle> = k; } public void unLink<rolle>(){ <rolle> = null;} public <Klasse2> getLink<rolle>(){ return <rolle>; } } 38 Uni-direktionale Assoziationen Angabe von mehrwertigen Assoziationen in folgender Form: <Klasse1> ?..* - <rolle> <Klasse2> public class <Klasse1>{ private Vector<Klasse2> <rolle>; ... } Beziehung über den Rollennamen als Feld-Attribut einbinden in Richtung der Navigierbarkeit Zugriff über öffentliche Verwaltungsoperationen wie im Klassendiagramm spezifiziert 39 Uni-direktionale Assoziationen Verwaltungsoperationen für mehrwertige Assoziationen <Klasse1> ?..* - <rolle> <Klasse2> public class <Klasse1>{ private Vector<Klasse2> <rolle>; public void link<rolle>(<Klasse2> k){ <rolle>.addElement(k); } public void unLink<rolle>(<Klasse2> k){ <rolle>.removeElement(k);} public <Klasse2> getLink<rolle>(int pos){ return <rolle>.elementAt(pos);} } 40 Uni-direktionale Assoziationen Zusätzlich bei Verwaltungsoperationen zu beachten ist die Fehlerbehandlung: Dateninvarianten sicherstellen in link- und unlink-Operationen Bei optionalen Beziehungen muss zusätzlich noch beim Zugriff überprüft werden, ob eine Objektbeziehung besteht Fehlerbehandlung bei Bibliotheksfunktionen [Verhalten bei Auftreten eines Fehlers analog zu Verwaltungsoperationen von Attributen] 41 Bi-direktionale Assoziationen Angabe: Beziehung über die Rollennamen als Attribut einbinden für beide Klassen (wie uni-direktional in beide Richtungen) Link- und unlink-Operationen beider Klassen stellen aus Symmetriegründen Beziehung in beide Richtungen her <Klasse1> - <rolle1> - <rolle2> <Klasse2> Achtung: Überprüfe, ob beteiligte Objekte nicht schon in anderer Beziehung: in diesem Fall unlink für alte Beziehung notwendig 42 Bi-direktionale Assoziationen Verwaltungsoperation link exemplarisch im beiderseits einwertigen Fall: <Klasse1> - <rolle1> - <rolle2> public class <Klasse1>{ private <Klasse2> <rolle2>; public void link<rolle2>(<Klasse2> k){ if (rolle2 != null) unlink<rolle2>(); <rolle2> = k; if (k.getLink<rolle1>()!= this){ if (k.getLink<rolle1>()!= null) k.unlink<rolle1>(); k.getLink<rolle1>() = this; } } <Klasse2> 43 Bi-direktionale Assoziationen Verwaltungsoperationen allgemeiner Fall: <Klasse1> - <rolle1> - <rolle2> <Klasse2> Man muss vier Fälle unterscheiden (alle Kombinationen von einwertig & mehrwertig in beide Richtungen der Navigierbarkeit) Beachte wie gehabt zusätzlich Datenstruktur-Invarianten, Besonderheiten bei optionalen Beziehungen und Fehlerbehandlung bei Bibliotheksfunktionen 44 Aggregation und Komposition Sind Spezialfälle uni-direktionaler Assoziationen Implementierung wie geschildert über Attribut für Rollennamen Verwaltungsoperationen mit anderen Namen, aber ähnlicher Funktionalität 45 Aggregation und Komposition Sonderfall: Anbindung einer Containerklasse im Singletonmuster zur Verwaltung von Objekten einer Klasse <Klasse> public class <Klasse>Container{ private static <Klasse>Container unique = null; private Vector<Klasse> alle<Klasse> = new Vector<Klasse>(); private <Klasse>Container(){} public static <Klasse>Container instance(){ if (unique == null){ unique = <Klasse>Container();} return unique;} public void add<Klasse>(<Klasse> k){ alle<Klasse>.addElement(k);} public void delete<Klasse>(<Klasse> k){ alle<Klasse>.removeElement(k);} public <Klasse> get<Klasse>(int pos){ return alle<Klasse>.elementAt(pos);} } 46 Aggregation und Komposition Sonderfall: Anbindung einer Containerklasse im Singletonmuster zur Verwaltung von Objekten einer Klasse <Klasse> public class <Klasse>Container{ ... public static <Klasse>Container instance(){...} public void add<Klasse>(<Klasse> k){...} public void delete<Klasse>(<Klasse> k){...} public <Klasse> get<Klasse>(int pos){...} } ... <Klasse>Container con = <Klasse>Container.instance(); <Klasse> o = new <Klasse>(); con.add<Klasse>(o); ... 47 Schnittstellen Angabe von Schnittstellen in folgender Form: interface <Schnittstelle>{<Rumpf>} 48 Schnittstellen Die implements-Beziehung: class <Klasse> implements <Schnittstelle> {...} Implementierung mehrerer Schnittstellen: Schnittstellen durch Komma getrennt auflisten Klassen können gleichzeitig Unterklasse einer Oberklasse sein und mehrere Schnittstellen implementieren Eine Klasse muss alle Operationen einer implementierten Schnittstelle konkret implementieren! 49 Schnittstellen Beispiel: Iterator-Muster (Klassenbibliothek) <<interface>> Iterable<E> iterator():Iterator<E> <Klasse>Container Vector public class <Klasse>Container implements Iterable<Klasse> { private Vector<Klasse> alle<Klasse> = new Vector<Klasse>(); ... public Iterator<Klasse> iterator(){ return alle<Klasse>.iterator(); } } 50 Schnittstellen Beispiel: Iterator-Muster (Klassenbibliothek) <<interface>> Iterable<E> <Klasse>Container Vector Damit läßt sich der Container unabhängig von seiner Implementierung durchlaufen Iterator<Klasse> it = <Klasse>Container.iterator(); while(it.hasNext()){ <Klasse> o = it.next(); ... 51 Schnittstellen Beispiel: Ereignisbehandlung (nächstes Kapitel) 52 Pakete Einbindung von Klassen in Pakete zu Beginn einer Datei: package <meinPaket>; <Klassendefinition> Import und Zugriff auf Klassen anderer Pakete zu Dateibeginn import <paketname>.<Klasse>; 53