Ziele Erstellen größerer Softwaresysteme in Java: Vorlesung Informatik II Objektorientierter Entwurf von Softwaresystemen mit UML Anwenden von Java-Bibliotheken Implementierung von UML-Modellen in Java Universität Augsburg Sommersemester 2011 Selbstständiges Erarbeiten von Problemlösungen Prof. Dr. Robert Lorenz Eigenverantwortliches Erarbeiten von Lerninhalten Lehrprofessur für Informatik Präsentation von Problemlösungen 00. Organisatorisches 1 Wie? 2 Verwaltungssysteme Üben, Üben, Üben (wie schon letztes Semester) LectureReg: Verwaltungssystem der Lehrstühle https://peaches.informatik.uni-augsburg.de/lecturereg/ Übungsblätter bearbeiten Vorrechnen Betreutes Programmieren Angemessen: 6-8 Stunden pro Woche Anmeldung zu Übungsgruppen Anmeldung zu Klausuren Abfrage von Ergebnissen Registrierung, um Rundmails zu erhalten Anmeldefristen: Lehrstuhl-Webpage, Rundmails, Vorlesung 3 4 Verwaltungssysteme Vorlesungsbetrieb Zwei Vorlesungen pro Woche im Hörsaal I STUDIS: Verwaltungssystem des Prüfungsamts https://www.studis.uni-augsburg.de/studisaugsburg/fai/ Dienstag 10:00 – 11:30 Donnerstag 10:00 – 11:30 Anmeldung zu Prüfungsmodulen Teilnahme an den Klausuren ohne STUDISAnmeldung ist NICHT möglich Vorlesungsfrei 2. + 14. + 23. Juni Anmeldefristen: Lehrstuhl-Webpage, Rundmails, Vorlesung Der Lehrstuhl ist nicht für Studis zuständig Bei Problemen: Prüfungsamt! 5 Vorlesungsbetrieb 6 Vorlesungsbetrieb Folien zur Vorlesung Einführung in die Softwaretechnik (Wirtschaftsinformatiker) jeweils ab Montag, 12.00 Uhr (Webseite des Lehrstuhls) Vorlesungen prüfungsrelevant bis einschließlich 9. Juni (5 Übungsblätter) stehen ausgedruckt zur Verfügung (Studiengebühren) 7 8 Übungsbetrieb Übungsbetrieb Übungsblätter Übungsgruppen Wöchentliche Ausgabe Montags, 12 Uhr, Start gestern 12 Übungsgruppen zu maximal 25 Teilnehmern keine direkte Anmeldung möglich Anmeldung in Vorregistrierungsgruppe und Prioritätensystem Termine: siehe Lecturereg 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 Start ab kommenden Montag, 09.05. Kennenlernen, Fragen und Teambildung Bewertung: 1 Übungspunkt pro Aufgabe 9 Übungsbetrieb 10 Übungsbetrieb Übungsgruppen Übungsgruppen Wiederholergruppe für Wiederholer ab SS 2009, die nicht am Übungsbetrieb teilnehmen Bewertung beim Vorrechnen: 1 Übungspunkt pro Aufgabe Einmal Vorrechnen ist Pflicht! 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 12 Übungsbetrieb Übungsbetrieb Betreutes Üben/Programmieren Globalübung Bearbeiten zusätzlicher Übungs-/Programmier-Aufgaben mit Unterstützung durch Tutoren Nach Korrektur eines Übungsblatts Termin: Fragen, häufige Fehler, alternative Lösungen, Nachbetrachtungen, kein Vorrechnen Mittwoch, 14.00 – 19.00 Raum 1001 N Beginn: 04.05. Betreuung durch den Lehrstuhl Zusatzaufgabe bringt einen Übungspunkt Termin: Dienstag, 8.15 – 9.45, Informatik-Hörsaal 2045 Beginn: 24.5. 13 Prüfungsmodalitäten 14 Prüfungsmodalitäten Für ALLE gilt: 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 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 Achtung: Studis-Anmeldung führt zur Bewertung auch bei NichtTeilnahme (als nicht bestanden) Bereiten Sie sich aus denselben Gründen gleich auf die 1. Klausur gründlich und gewissenhaft vor Je nach Studiengang unterscheiden sich Anmelde-Modalitäten Anzahl der Prüfungsversuche 15 16 Prüfungsmodul Informatik I Prüfungsmodul Informatik I Bachelor Informatik / Informatik & Multimedia, PO 2009: Andere Informatik-Studiengänge, Nebenfächler: Jede Klausur ist ein eigenes Prüfungsmodul für jede Klausur (Prüfung) ist Studis-Anmeldung erforderlich Jede Klausur ist ein eigenes Prüfungsmodul für jede Klausur (Prüfung) ist Studis-Anmeldung erforderlich Man muss jede Prüfungsmöglichkeit nutzen Man darf an beiden Klausuren teilnehmen Es zählt die bessere Note aus beiden Klausuren 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 Anzahl der Prüfungsversuche, Obergrenze Semesteranzahl bitte eigene PO lesen! Sonderregelung: Man kann mit 2. Klausur Note verbessern (gilt u.a. für Informatik 1, Informatik 2) 17 Prüfungsmodul Einf. Softwaretechnik 18 Klausur Bachelor Wirtschaftsinformatik: Zulassung (gilt für alle trotz unterschiedlicher POs!) Jede Klausur ist ein eigenes Prüfungsmodul für jede Klausur (Prüfung) ist Studis-Anmeldung erforderlich Mindestens 20 Übungspunkte (WIN: 10 Punkte) aus… Es gibt keine Beschränkung der Anzahl der Prüfungsversuche Bei Bestehen kann die Note nicht mehr verbessert werden …Bearbeitung von Übungsblättern 1 Punkt für jede richtig bearbeitete Aufgabe 4 Aufgaben pro Übungsblatt Informatik 1 / Informatik 2 sind Pflichtveranstaltungen müssen bis spätestens zum 8. Semester bestanden sein …Vorrechnen in den Übungsgruppen 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 …Bearbeitung der zusätzlichen Aufgabe im betreuten Programmieren 1 Punkt für jede korrekt vorgerechnete Aufgabe Maximal 12 Punkte aus Vorrechnen einbringbar 1 Punkt für richtig bearbeitete Aufgabe 19 20 Klausur Klausur Zulassung (gilt für alle trotz unterschiedlicher POs!) Bewertung Mindestens 1 mal Vorrechnen in der Übungsgruppe Für je 5 Punkte über der Zulassungsgrenze (20 Punkte / WIN: 10 Punkte) gibt es einen Bonuspunkt es sind bis zu 10 Bonuspunkte erreichbar Anmeldung zur Klausur in LectureReg und Studis (Anmeldezeiträume werden noch bekannt gegeben) 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 21 Klausur 22 Software Programmiersprache Java Alte Zulassungen Zulassungen/Bonuspunkte seit SS 09 bleiben erhalten JDK 6 Update 5:http://java.sun.com/javase/downloads/index.jsp Zulassungen vor SS 09 zählen nicht API: http://java.sun.com/javase/6/docs/api/index.html Termine 1. Klausur: letzte Veranstaltungswoche, Donnerstag, 28.07. 2. Klausur: Ende WS Entwicklungsumgebung Eclipse: http://www.eclipse.org 23 24 Literatur/Materialien Literatur/Materialien Programmiersprache Java UML (Unified Modeling Language) Java ist auch eine Insel: Christian Ullenboom, 2006 (http://www.tutego.com/javabuch/) http://www.oose.de/notationuml14.htm Lehrbuch der Objektmodellierung: Heide Balzert, 2005 The Java Tutorial: M. Campione, K. Walrath, 1998 (http://java.sun.com/docs/books/tutorial/) Objektorientierte Softwareentwicklung: Bernd Oesterreich, 2001 Lehrbuch Grundlagen der Informatik: Helmut Balzert, 2005 25 26 Bei Fragen Lehrstuhl-Webpage http://www.informatik.uni-augsburg.de/lehrstuehle/inf/ Vorlesung Informatik II E-Mail-Adressen [email protected] [email protected] [email protected] Universität Augsburg Sommersemester 2011 Prof. Dr. Robert Lorenz Sprechstunde Mittwoch, 10:00 – 11:00 Raum 1023 N (neues Gebäude) Lehrprofessur für Informatik Studentenforum 01. Softwareentwurf 27 1 Softwareentwurf Softwareentwurf Teilgebiet des Software-Engineering Forderungen Ziel: Systematisierung / Vereinheitlichung des Entwurfs Systematischer und nachvollziehbarer Entwurf zur Erleichterung der Pflege, Wartung und Erweiterung des Programms Teilweise computergestützt (Softwareentwicklungstools) Arbeitsteiliger Entwurf (bei großen Problemstellungen) - frühzeitige Strukturierung - Zerlegung in Teilprobleme 2 Softwareentwurf 3 Strukturierung Entwurfsprinzipien Mit Strukturierung wird eine adäquate Darstellung der logischen Eigenschaften von Daten und Abläufen und der Zusammenhänge zwischen ihnen bezeichnet. 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 5 Strukturierung Strukturierung Algorithmische Strukturierung (Informatik 1): Datenstrukturierung (Informatik 1+2): Strukturierte Darstellung des logischen Ablaufs durch Darstellung der logischen Eigenschaften und Beziehungen zwischen den zu bearbeitenden Objekten durch geeignete Datentypen Sequenzen, d.h. lineare Abfolgen von Anweisungen Verzweigungen in Abhängigkeit von Bedingungen Wiederholungen von Anweisungsfolgen 6 Strukturierung 7 Schrittweise Verfeinerung Vorgehen Prinzip 1: Top-Down-Vorgehen Elementare Operationen (und Datenstrukturen) einer komplexen Anwendung sind meist sehr einfach. Programmiersprachen-unabhängiger Entwurf der groben Funktionalität einer Anwendung mit abstrakten Operationen und Datentypen (Benutzerorientiert) 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: Verfeinerung der im ersten Schritt benutzten Operationen, d.h. "Implementierung" mit weniger abstrakten Operationen und Datentypen. Wie gestaltet man den Schritt von den elementaren Operationen zu der komplexen Funktionalität einer Anwendung und umgekehrt möglichst überschaubar und einfach? Wiederholung des Verfeinerungsschrittes, bis nur noch (Programmiersprachen-abhängig) zur Verfügung stehende Ablaufstrukturen und Elementaroperationen verwendet werden. 8 9 Schrittweise Verfeinerung Modularisierung Prinzip 1: Top-Down-Vorgehen Prinzip 2: Bottom-Up-Vorgehen (Informatik 1) Erfordert simultane, aufeinander abgestimmte Verfeinerung und Konkretisierung von: Abgeschlossene Teilaufgaben werden zuerst durch Programmstücke realisiert. – Operationen, – Kontrollflüssen (Ablaufstrukturen), – Datenstrukturen Anschließend Zusammenfügen der Teillösungen zu größeren Einheiten. Erfordert Modularisierung des Problems in Teilprobleme (Teilaufgaben) d.h. die einzelnen Bestandteile von Algorithmen sollten auf gleichem Niveau verfeinert werden. 10 Modularisierung 11 Modularisierung Beispiele für Bottom-Up-Vorgehen aus Informatik 1 Definition Modularisierung Mathematische Aufgabenstellungen: Zerlegung von Problemen in Teilprobleme, die zunächst einfache arithmetische Operationen – klar voneinander abgegrenzt sind später komplizierte Operationen (Matrizenrechnung, numerische Integration) – getrennt bearbeitet werden können Erstellung von Programmbibliotheken: – deren Lösungen nebenwirkungsfrei gegen Alternativlösungen austauschbar sind (keine "Seiteneffekte"). zunächst einfache Standardalgorithmen spätere Verwendung beim Entwurf komplizierter Algorithmen 12 – weitgehend unabhängig voneinander sind 13 Modularisierung Modularisierung Vorteile Charakteristika von Modulen: Reduzierung der Komplexität eines Problems durch Zerlegung in überschaubare Einzelprobleme Keine Berücksichtigung von Reihenfolgeabhängigkeiten (im Unterschied zur schrittweisen Verfeinerung) Einzelne Module können unabhängig voneinander getestet oder verifiziert werden Einzelne Module sind austauschbar und erweiterbar (Baukastenprinzip) Spezifikation weitgehend unabhängiger Teilaufgaben mit klar definierten Schnittstellen (Prinzip der Einkapselung) Späteres Zusammenfügen der einzelnen Teillösungen über die vereinbarten Schnittstellen Erlaubt unproblematischen Übergang zu Nachfolgeversionen eines Softwareprodukts durch Austausch einzelner Module 14 Modularisierung 15 Modularisierung Prinzip der Einkapselung Datenstruktur-Invariante Zusammenfassung bestimmter Programmteile (Daten, Funktionen) Eine Eigenschaft einer Datenstruktur, die nach Initialisierung gilt und durch alle Operationen darauf erhalten bleiben soll, heißt Invariante der Datenstruktur. 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 Durch beliebigen Zugriff kann ein Zusammenhang zwischen den beteiligten Variablen gestört werden. (Bsp.: Fallstudie am Ende) Sicherstellung von Datenstruktur-Invarianten 16 17 Modularisierung Modularisierung Beispiel für Einkapselung: Funktionen (siehe Informatik 1) Definition Modul Wiederholt ausgeführte, ähnliche Teile werden durch Parametrisierung zusammengefasst Ein Modul besteht aus einer Sammlung von VariablenVereinbarungen und Funktionen 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 Variablen und Funktionen werden in öffentliche und private aufgeteilt. Aber: Funktionen reichen nicht, um Größen durch Einkapselung vor beliebigem Zugriff zu schützen (Bsp.: Fallstudie am Ende) Kein beliebiger Zugriff auf private Variablen und Funktionen Die öffentlichen sind außerhalb des Moduls verfügbar, die privaten nur innerhalb (diese sind also eingekapselt) 18 Modularisierung 19 Modularisierung Typische Realisierung von Modulen Schnittstelle eines Moduls Eine Datenstruktur wird meist als Sammlung privater Variablen realisiert Die Sammlung der öffentlichen Variablen und FunktionsDeklarationen eines Moduls nennt man dessen Schnittstelle (interface). Die öffentlichen Funktionen werden dann so angelegt, dass sie die erwünschten Datenstrukturinvarianten erhalten Damit ist der unkontrollierte Zugriff auf private Variable unterbunden Angabe durch die Signatur: Bezeichner der Variablen und Konstanten mit Typ Prototypen der Funktionen Beispiel: h-Datei in C 20 21 Modularisierung Modularisierung Fallstudie: Implementierung einer Menge ganzer Zahlen Fallstudie: Implementierung einer Menge ganzer Zahlen Öffentlicher Teil der Schnittstelle für eine Datenstruktur Set zur Repräsentation von Mengen in C: Implementiere Set als einfach verkettete Liste: 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 typedef struct knoten { int wert; struct knoten * next; } Knoten; typedef struct set { knoten * start; int size; } Set; 22 Modularisierung 23 Modularisierung Fallstudie: Implementierung einer Menge ganzer Zahlen Fallstudie: Implementierung einer Menge ganzer Zahlen Implementiere Set als einfach verkettete Liste: Implementiere Set als Bitvektor fester Länge: Datenstrukturinvarianten: „Liste sortiert und wiederholungsfrei“ „Wert von size entspricht Anzahl der Knoten“ typedef struct set { int werte[1000]; int size; } Set; Leere Menge: Menge {1,2,4}: null 1 2 4 null 24 25 Modularisierung Modularisierung Fallstudie: Implementierung einer Menge ganzer Zahlen Fallstudie: Implementierung einer Menge ganzer Zahlen Implementiere set als Bitvektor fester Länge: DISKUSSION: Datenstrukturinvarianten: „Vektor werte hat nur die Werte 0 und 1“ „Wert von size entspricht Anzahl der 1sen im Vektor werte“ Welche Implementierung ist (in welchen Fällen) weniger Speicherplatz- bzw. Zeitaufwendig? 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 Überlege verschiedene Möglichkeiten, wie ein Programmierer dummerweise Datenstruktur-Invarianten zerstören könnte ZUSÄTZLICHE SPRACHKONSTRUKTE FÜR EINKAPSELUNG NOTWENDIG 26 27 Modellbasierter Entwurf Modularisierung Zusammenfassung Entwicklung komplexer Anwendungen benötigt Strukturierung Zerlegung eines großen Programmsystems in einzelne, überschaubare und sinnvolle Teile Modellbildung vor Programmierung Abschirmung und damit Schutz privater Variablen UML (Unified Modeling Language) zur Programmiersprachenunabhängigen Modellierung komplexer Systeme: Verbergen von Implementierungsdetails: Trennung „Was wird getan“ (deklarativ) von „Wie wird es getan“ (operationell) Austauschbarkeit von Implementierungen Statische Modelle: Strukturierung der Daten (Klassendiagramm) Möglichkeit zur unabhängigen Implementierung der Teile, wenn die Schnittstellen geklärt sind. Dynamische Modelle: Strukturierung der Abläufe (Sequenzdiagramm) 28 29 UML UML Charakteristika: UML in dieser Vorlesung Modellierungssprache zur Dokumentation von Analyse, Entwurf und Implementierung objektorientierter Software Sprachumfang zu umfangreich zur Darstellung in einer Vorlesung Vereinigt eine Vielzahl graphischer und textueller Beschreibungsmethoden (Diagrammtypen) Vorlesung ist keine vollständige UML-Dokumentation! Beinhaltet kein Vorgehensmodell zur Software-Entwicklung, gibt aber einen Rahmen vor. Stattdessen: Vorteile: Unabhängigkeit von Programmiersprache Graphische Darstellung (verständlich für Anwender) Viele Details erst in der Anwendung voll verständlich Einführung in Grundkonzepte der wichtigsten Diagrammtypen (Klassen-, Sequenz-Diagramm) Entwicklung einer Basis für Entwicklung einfacherer Anwendungen und selbstständige detailliertere Einarbeitung 30 Ein Vorgehensmodell zur Modellierung Ein Vorgehensmodell zur Modellierung Analyse Top-Down-Vorgehen grob in 3 Phasen: Pflichtenheft Analyse Was soll gemacht werden? (UML) Entwurf Wie wird’s gemacht? (UML) Implementierung 31 Prototyp Entwurf (konkrete Programmiersprache) Analysemodell Entwurfsmodell Benutzeroberfläche Fachkonzept Analysemodell Datenhaltung Test Bibliotheken Datenbank (Java-)Programm 32 33 Ein Vorgehensmodell zur Modellierung Manche Diagramme lassen sich eindeutig einer der Modellierungsphasen (Analyse, Entwurf) zuordnen Ein Vorgehensmodell zur Modellierung Sinn, Zweck und Bedeutung von Vorgehensmodellen 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 „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) Wir werden das Vorgehensmodell und die Trennung in Analyse- und Entwurfsphase nicht besprechen 34 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, … Vorlesung Informatik II Universität Augsburg Sommersemester 2011 Re-Engineering: Anleitungen, Hilfesystem, Bildschirmmasken, Benutzerdialoge, Funktionalität Pflichtenheft: Textuelle Beschreibung dessen, was das System leisten soll, detaillierter als das Analysemodell 36 Prof. Dr. Robert Lorenz Lehrprofessur für Informatik 02. JAVA: Erstes Programm 1 Das erste Java-Programm 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 class SayHello { ... } Deklaration einer Klasse SayHello Eine Klasse ist ein strukturierter Datentyp (ein Modul) //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“); } } 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) 2 Das erste Java-Programm 3 Das erste Java-Programm class SayHello { ... } class SayHello { ... } Deklaration einer Klasse SayHello Ein C-Programm besteht aus einer Sammlung von Funktionen 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) 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 4 5 Das erste Java-Programm Das erste Java-Programm public static void main(String args[ ]) { ... } public static void main(String args[ ]) { ... } Deklaration der Operation main Deklaration der Operation main Genau eine der Klassen eines Programms muss die mainFunktion enthalten (die Programmklasse) main hat immer folgende Modifikatoren: public: öffentliche Operation – von aussen aufrufbar Bei Start wird automatisch main aufgerufen static: Klassenoperation – ohne Objekt aufrufbar [man benötigt kein Objekt der Programmklasse für den Aufruf] 6 Das erste Java-Programm 7 Das erste Java-Programm public static void main(String args[]) { ... } public static void main(String args[ ]) { ... } Deklaration der Operation main Ein C-Programm enthält genau eine Funktion main main hat immer folgende Parameter: In C werden Zeichenketten durch Pointer auf char repräsentiert (char *) 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 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 Das erste Java-Programm { ... } - Blöcke System.out.println(...); Geben wie in C Gültigkeitsbereiche an Aufruf der Bibliotheksfunktion println Beispiele: Klassenrümpfe, Funktionsrümpfe 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 10 Das erste Java-Programm 11 Das erste Java-Programm System.out.println(...); System.out.println(...); Aufruf der Bibliotheksfunktion println In C gibt es eine Funktions-Bibliothek (gegliedert in h-Dateien) println gibt übergebene Zeichenkette auf Kommandozeile aus Bibliotheksklassen sind hierarchisch in Pakete gegliedert: In Java gibt es eine Klassen-Bibliothek (hierarchisch gegliedert in Pakete): http://java.sun.com/javase/6/docs/api/ 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 13 Compilieren und Ausführen Compilieren und Ausführen Vorgehen Vorgehen 1. Java-Programme werden von einem Prozessor-unabhängigen Java-Compiler in sog. Byte-Code übersetzt. Erstelle .java - Quelldateien mit Texteditor Dieser kann vom Prozessor nicht direkt ausgeführt werden. Compiliere Dateien mit Kommandozeilen-Befehl javac <Dateiname>.java Ergebnis: Ausführbarer Byte-Code in class- Dateien 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) Führe Programm aus durch Interpretation der class – Programmdatei mit Kommandozeilen-Befehl java <Programmdateiname>.class 14 Compilieren und Ausführen 15 Compilieren und Ausführen Anleitung Vorteile: Nur ein Compiler für alle Prozessortypen Installiere Java SE JDK 6 (auch J2SE SDK genannt) Download unter http://java.sun.com Java plattform-unabhängig exakt definiert Übersetzte Java-Programme laufen ohne Neuübersetzung auf allen Plattformen mit Java-Interpreter Jetzt müssen folgende Kommandos (Kommandozeilenfenster) ein erfolgreiches Ergebnis liefern: C:\Java\jdk\bin\java.exe -version C:\Java\jdk\bin\javac.exe -help Nachteile: Übersetzte Programme laufen langsamer Mit javac wird der Java-Compiler aufgerufen Mit java wird ein Java-Programm ausgeführt Für jeden Prozessortyp einen neuen Interpreter 16 17 Compilieren und Ausführen Compilieren und Ausführen System konfigurieren System konfigurieren Setzen von Umgebungsvariablen: Angabe von Pfaden ... Jetzt müssen folgende Kommandos erfolgreich sein: set JAVA_HOME java -version javac -help ... 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 Mehr Java-Programme 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 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 Eclipse public static void main (String args[]) Eclipse bietet eine Entwicklungsumgebung für Java (und andere Programmiersprachen) Ähnlich wie in C: Deklaration von i gilt nur lokal im { ... } - Block Frei erhältlich (open source) unter www.eclipse.org if-else- Anweisung für Fallunterscheidungen .zip-Datei downloaden und in beliebigem Verzeichnis entpacken (z.B. unter C:\...\Java) Achtung: vorher JDK installieren for- Anweisung für wiederholte Ausführung von Anweisungen Unterschiedlich zu C: Start: Ausführen von eclipse.exe Mit Feldname.length kann man die Länge eines Feldes abfragen Workspace am besten auf Datenpartition D: anlegen 22 23 Eclipse Programme erstellen und ausführen in Eclipse: Vorlesung Informatik II Java-Projekt anlegen Universität Augsburg Klasse anlegen mit main-Methode (und Paket-Angabe) Sommersemester 2011 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 Prof. Dr. Robert Lorenz Lehrprofessur für Informatik 03. JAVA: Grundlagen 24 1 Primitive Datentypen Primitive Datentypen Es gibt diesselben primitiven Datentypen wie in C Überblick Zusätzlich: boolean für Wahrheitswerte byte für Bytes 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 ==,!=,&,|,^, &&,||,! +,-,+,*,/,%,<, <=,>,>=,==,!=, ~,++,-+,-,+,*,/,%,<, <=,>,>=,==,!=, ++,-... ... ... ... ... 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 Byte Byte Byte Byte Byte 2 Primitive Datentypen Primitive Datentypen Konstanten ähnlich wie in C: 012 0x3F 12 -5 3L 3.7 1.2e+2 'A' \b,\n,\t \", \', \\ \0??? \u???? 3 Operatoren ähnlich wie in C: (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) 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 4 5 Primitive Datentypen 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 Deklaration wie in C: boolean b = true;//mit Wertzuweisung int i, j;//ohne Wertzuweisung double d = 3.14; char c = 'A'; short, int, long, float, double int, long, float, double int, long, float, double long, float, double float, double double Durch Deklaration wird der notwendige Speicherplatz für Datentyp reserviert 6 Primitive Datentypen 7 Primitive Datentypen Wertzuweisungen wie in C: Explizite Typeinengung durch eine Typcast mittels vorangestelltem (Typ): boolean b = true;//in der Deklaration b = false;//nach der Deklaration int i; float b=10.5f; i = (int) b*3;//Wert von i ist 30 Durch Zuweisung wird einer Variablen ein Wert zugewiesen: Dieser Wert wird also an der reservierten Speicherstelle eingetragen/gespeichert (u.U. mit Informationsverlust) Der Wert kann nur aus dem zugehörigen Wertebereich des Datentyps kommen: Wie in C kommt es zu automatischen Wertumwandlungen (Ausweitung oder Einengung) 8 9 Primitive Datentypen Referenz-Datentypen Zeiger: Alle anderen Datentypen sind Klassen oder Felder 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 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 In Java werden bei primitiven Rückgabetypen grundsätzlich Werte zurückgegeben (niemals Zeiger) 10 Klassen 11 Klassen Deklaration wie bei primitiven Typen: <Typ> <Vname> Deklaration wie bei primitiven Typen: <Typ> <Vname> Frame f;//ohne Wertzuweisung String s = new String(“Du”);//mit Wertzuweisung Variablen einer Klasse sind immer Zeiger Bei der Deklaration wird Speicherplatz für einen Zeiger reserviert 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 12 13 Klassen Klassen Wertzuweisungen 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 StringBuffer s1 = new StringBuffer(“Hallo”); //s1 zeigt auf Speicherstelle mit Eintrag “Hallo” Eine Referenz in Form der Speicheradresse des Objekts der rechten Seite wird in der Variable der linken Seite gespeichert Stringbuffer ist eine weitere vordefinierte Bibliotheksklasse zur Verwaltung von Zeichenketten StringBuffer s2 = new StringBuffer(“World”); //s2 zeigt auf Speicherstelle mit Eintrag “World” null ist die Nullreferenz (entspricht NULL in C) null ist die Voreinstellung bei Klassen 14 Klassen 15 Klassen Zeiger: 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 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) 16 17 Klassen Klassen Parameterübergabe und Rückgabewerte Typumwandlungen 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); } Unter bestimmten Umständen können Klassen ineinander umgewandelt werden Mehr dazu im UML-Teil (Ober- und Unterklassen) s1 zeigt auf Speicherstelle mit Eintrag “Hallo” s2 zeigt auf Speicherstelle mit Eintrag “WorldHallo” s3 zeigt auf Speicherstelle mit Eintrag “WorldHallo” 18 Arrays (Felder) 19 Arrays Wie in C kann man Felder beliebigen Datentyps mit fester Länge definieren Wie in C kann man Felder beliebigen Datentyps mit fester Länge definieren Wie in C sind Feld-Variablen Zeiger Wie in C sind Feld-Variablen Zeiger Deklaration: Erzeugung: <Typ> <meinArray>[] <meinArray> = new <Typ>[<Länge>] 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) Reserviert Speicherplatz für alle Elemente des Feldes Der Wert der Variable ist ein Zeiger auf diesen Speicherplatz (auf das erste Feldelement) 20 21 Arrays 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 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(); 22 Arrays 23 Zeiger Weitere Besonderheiten: Zusammenfassung Länge eines Arrays abfragbar mit <Variablename>.length: In Java gibt es keine explizite Dereferenzierung Es gibt keine Zeiger auf Werte primitiven Typs Alle Variablen nichtprimitiven Typs sind Zeiger 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: Für Variablen nichtprimitiven Typs wird mit new <Konstruktor>(<Parameterliste>) Speicherplatz für ein Objekt des Typs reserviert und werden die Komponenten initialisiert LinkedList, ArrayList, HashSet, TreeSet, HashMap, TreeMap, Vector, ... (siehe später auch UML) 24 25 Zeiger Funktionen Zusammenfassung Funktionen sind immer Teil einer Klasse 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! Deklaration Genauso wie in C in der Form <Rückgabetyp> <Funktionsname>(<Parameterliste>) mit <Parameterliste> := <Typ1> <Parameter1>, ... 26 Funktionen 27 Kontrollstrukturen Funktionen sind immer Teil einer Klasse Fallunterscheidungen wie in C: Aufruf if(<Bedingung>) { <Anweisungen> } else { <Anweisungen> } Über Punkt-Operation, angewendet auf Variable der Klasse oder den Klassennamen selbst bei static-Funktionen: <Variable>.<Funktionsname>(<Werte>) <Klassenname>.<Funktionsname>(<Werte>) switch(<Ausdruck>){ case <Wert>: <Anweisungen> default: <Anweisungen> } Ähnlich wie Zugriff auf Komponenten von strukturierten Datentypen in C Wie in C müssen Werte zu Eingabeparametern passen 28 29 Kontrollstrukturen Hüllklassen Wiederholungen wie in C: Java stellt Hüllklassen (wrapper classes) für die primitiven Datentypen zur Verfügung: while(<Bedingung>) { <Anweisungen> } Konstruktoren machen aus Elementen primitiven Typs Objekte: public <Hüllklasse> (<Datentyp> <value>) do { <Anweisungen> } while(<Bedingung>); Umkehrmethoden gewinnen die Elemente primitiven Typs zurück: public <Datentyp> <Datentyp>Value() for(<Wertzuweisung>;<Bedingung>;<Anweisung>) { <Anweisungen> } 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) 30 Zeichenketten 31 Zeichenketten Im Gegensatz zu C gibt es in Java für Zeichenketten eigene Datenstrukturen Klasse String Für die Repräsentation von Zeichenketten gibt es vordefinierte Bibliotheksklassen Diese Klassen definieren repräsentiert Zeichenketten mit zahlreichen Operationen Zeichenketten sind konstant, d.h. es gibt keine Operationen zum Ändern einer einmal konstruierten Zeichenkette verschiedene Zeichenketten-Operationen verschiedene Konstruktoren zur Erzeugung von Zeichenketten-Objekten 32 33 Zeichenketten Zeichenketten Klasse String Klasse String Konstruktoren (Auswahl) Operationen (Auswahl) String() int length()//Länge String(char[] value) char charAt (int index)//Buchstabe an Position index String toUpperCase()//Umwandlung in Großbuchstaben wandelt das char-Feld value in einen String um int compareTo (String anotherString)//Lexikographisch vergleichen String(String value) boolean startsWith(String prefix)//Ist prefix ein Anfangsstück? Kopierkonstruktor int indexOf(int ch)//Erster Index eines Zeichens String substring(int beginIndex, int endIndex)//Substring String(StringBuffer buffer) String concat (String str)//String str anhängen Wandelt buffer in einen String um String replace(char oldChar, char newChar)//Buchstaben ersetzen //…u.v.m. 34 Zeichenketten 35 Zeichenketten Klasse String Klasse StringBuffer Operationen zur Typumwandlung Repräsentiert dynamische Zeichenketten, die nach ihrer Konstruktion beliebig modifiziert werden können. static String valueOf(<Typ> val) Umwandlung nach String für jeden Grundtyp <Typ> außer byte und short Initialisierung mit einer leeren Zeichenkette fester Länge <Hüllklasse>(String str) Umwandlung von String in Hüllklasse char[] toCharArray() Umwandlung in ein neues char-Feld (und einige mehr) 36 37 Zeichenketten API Application Programming Interface http://java.sun.com/j2se/1.4.2/docs/api/ Klassenbibliothek mit vordefinierten Java-Klassen Klasse Stringbuffer Operationen (Auswahl) Aufgeteilt in Pakete, u.a.: StringBuffer insert(int offset, Object obj)//Einfügen Objekt StringBuffer insert(int offset, String str) //Einfügen String java.lang //Basisklassen (Automatisch eingebunden) System, Thread, Zeichenketten,... StringBuffer insert(int offset, float f) //Einfügen Zahl StringBuffer insert(int offset, int i) //Einfügen ganze Zahl java.util //Utilities Häufige Datenstrukturen, Zeit/Datum, Zufallszahlen,... StringBuffer delete(int start, int end)//Entfernen von Zeichen StringBuffer deleteCharAt(int index)/Entfernen eines Zeichens java.io //Ein- und Ausgabe Datenströme (Ein-/Ausgabe), Lesen/Schreiben von Dateien,... int capacity()//liefert Kapazität der Speicherstelle int length() //liefert die Länge der aktuellen Zeichenkette java.awt //grafische Ausgabe Fenster, Schaltflächen, Textfelder, Menüs, ... char charAt(int index)//liefert ein Zeichen …(u.v.m.) 38 39 API Application Programming Interface http://java.sun.com/j2se/1.4.2/docs/api/ Klassenbibliothek mit vordefinierten Java-Klassen Vorlesung Informatik II Universität Augsburg Import von Paketen der API am Programmanfang: Sommersemester 2011 import paketname.*; Macht Klassen und Funktionen benutzbar Ähnlich dem include-Befehl in C Prof. Dr. Robert Lorenz Lehrprofessur für Informatik 04. UML – Objekte und Klassen 40 1 Motivation 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 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 Wir werden allerdings nicht alle Details von Klassendiagrammen betrachten, sondern nur die wichtigsten Aspekte Das Klassendiagramm dient als statisches Modell der Strukturierung der Daten einer Anwendung Später sehen wir, wie man ein Klassendiagramm in Java implementieren kann 2 Objekte 3 Objekte Ein Objekt ist ein Gegenstand des Interesses Der Zustand eines Objekts wird beschrieben durch die Ausprägungen (Werte) seiner Eigenschaften (=Attribute) Objekte können Dinge, Personen und Begriffe sein Attribute modellieren die (Software-interne) Datenstruktur Objekte besitzen einen Zustand Es werden nur diejenigen Eigenschaften eines Objekts, die für die Anwendung relevant sind, modelliert Objekte reagieren mit definiertem Verhalten auf ihre Umgebung Attributwerte unterliegen Änderungen und repräsentieren die aktuellen (Software-internen) Daten Jedes Objekt besitzt eine Identität 4 5 Objekte Objekte Beispiel: Kreis (mit Attributen Mittelpunkt und Radius) Mittelpunkt = (0,10) Radius = 30 Objekt-Identitäts-Prinzip Ein Objekt ist unabhängig von seinen konkreten Attributwerten von allen anderen Objekten eindeutig zu unterscheiden Beispiel: Menge (mit Attribut Groesse und Elemente) Groesse = 1 Elemente = {5} Beispiel: Student (mit Attributen Name, Matrikelnummer,...) Name = „Huber“ Matrikelnummer = „1076894“ ... Objekte können also gleich, aber nicht identisch sein (zwei Objekte sind gleich, wenn sie dieselben Attribute haben und im selben Zustand sind) 6 Objekte 7 Objekte Das Verhalten eines Objekts wird beschrieben durch eine Menge von Operationen Das Verhalten eines Objekts wird beschrieben durch eine Menge von Operationen Operationen ermöglichen den Zugriff auf die (die Verwaltung der) Daten durch Operationen dienen wie Funktionen der funktionalen Abstraktion: Man legt zuerst nur fest, was berechnet werden soll Abfragen und Ändern von Attributwerten (Getter/Setter) Erzeugen von Objekten (Konstruktoren) Manipulieren von Beziehungen zwischen Objekten Berechnungen 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, …) … 8 9 Objekte Objekte Beispiel: Kreis setPosition(neuerMittelpunkt) setRadius(neuerRadius) ... Geheimnisprinzip: Beispiel: Menge istElement(einObjekt):boolean einfuegen(einObjekt) ... Also: kein direkter Zugriff auf Attributwerte Verwirklicht Prinzip der Einkapselung von Modulen Abfragen oder Änderungen von Attributwerten sind nur mittels der Operationen möglich Vorteile: Sicherstellen von Datenstruktur-Invarianten Datenstruktur mit weniger Aufwand änderbar Beispiel: Student getName():Zeichenkette ... 10 Klassen 11 Klassen Objekte mit gleichen Attributen und Operationen werden zu Klassen zusammengefasst Grafische Darstellung von Klassen Eine Klasse ist ein Schema zur Spezifikation von Gemeinsamkeiten einer Menge von Objekten mit denselben Eigenschaften und demselben Verhalten Namensfeld <Klassenname> Attributliste <Attribut> <Attribut> ... Operationsliste 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 <Operation> <Operation> ... Ein Klassenname ist ein Substantiv im Singular, beginnend mit einem Großbuchstaben [Attribute und Operationen: folgende Folien] 13 Klassen Klassen Beispiel: Kreis und Punkt Objekt-Klassen-Prinzip Ein Objekt ist Kreis Punkt position:Punkt radius:integer ... x:integer y:integer ... setPosition(in neuePosition:Punkt) getPosition():Punkt ... berechneFlaeche():double setX(in x:integer) getX():integer ... 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 14 Klassen 15 Exkurs: Namensraum Ein Namensraum ist ein Bereich (eines Modells), in dem jedes Element einen eindeutigen Namen besitzen muss Kohärenz-Prinzip Jede Klasse soll genau für einen (sachlogischen) Aspekt des Gesamtsystems verantwortlich sein In unterschiedlichen Namensräumen kann der gleiche Name in unterschiedlicher Bedeutung verwendet werden 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 17 Attribute Attribute Attribute Namen haben einen 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> sind von bestimmtem Typ können einen Anfangswert besitzen Attributnamen beginnen mit einem Kleinbuchstaben und werden nach fachlichen Gesichtspunkten gewählt können Multiplizität haben (mehrere Komponenten) können Einschränkungen unterworfen sein (DatenstrukturInvarianten) 18 Attribute Attribute Beispiel: Kreis und Rechteck Kreis Rechteck position radius ... position laenge breite ... ... 19 Attribut-Typen: Legen den Wertebereich eines Attributs fest (wie VariablenTypen in C) Dienen der möglichst präzisen Beschreibung der Daten aus fachlicher Sicht ... 20 21 Attribute Attribute Mögliche Attribut-Typen: Datentypen vs. Klassen Datentypen (Strukturierte) Datentypen können wie Klassen Attribute und Operationen besitzen Primitive UML-Datentypen: Boolean, String, Integer, UnlimitedNatural oder selbst definiert Strukturierter Datentyp Aufzählungstyp Klassen 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 22 Attribute 23 Attribute Grafische Darstellung von Datentypen ähnlich wie die von Klassen Beispiel: Student und Adresse Unterschiede: Student Dem Namen wird bei primitiven Datentypen das Schlüsselwort <<primitive>> vorangestellt name:String adresse:Adresse ... Dem Namen wird bei strukturierten Datentypen das Schlüsselwort <<datatype>> vorangestellt ... <<datatype>> Adresse Ort:String Strasse:String ... ... Angabe von Typen nach dem Attributnamen, abgetrennt durch einen Doppelpunkt : 24 25 Attribute Attribute Anfangswert Multiplizität Der Anfangswert legt fest, welchen Wert ein neu erzeugtes Objekt für ein Attribut annimmt Die Multiplizität legt die Anzahl der Werte (Komponenten) eines Attributs fest Angabe nach dem Namen in der Form Der Anfangswert kann zur Laufzeit des Programms beliebig geändert werden Angabe nach dem Namen, abgetrennt durch ein Gleichheitszeichen = [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 26 Attribute 27 Attribute Multiplizität Einschränkungen Attribute mit Multiplizität ungleich [1] kann man sich als Felder vorstellen 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) 28 29 Attribute Attribute Beispiel: Mengen ganzer Zahlen Klassenattribute Haben nur einen Wert für alle Objekte einer Klasse, existieren also nur einmal pro Klasse Menge groesse :Integer =0 elemente :Integer [0..*] {Anzahl der Werte von elemente = Wert von groesse} ... ... Klassenattribute existieren auch dann, wenn es für eine Klasse (noch) keine Objekte gibt Zugriff mittels <Klassenname>.<Attributname> Angabe wir normale Attribute, allerdings unterstrichen 30 Attribute 31 Operationen Operationen Beispiel: Student haben einen Namen Student können Ein- und Ausgabeparameter haben name:String adresse:Adresse anzahl :Integer =0 {anzahl>=0} ... können einen Rückgabetyp haben ... Speicherung der Anzahl der erzeugten Objekte 32 33 Operationen Operationen Namen 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 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 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 Operationen Beispiel: Kreis und Rechteck Kreis Rechteck ... ... anzeigen() ... anzeigen() speichern() speichern(in dateiname:String) ... 35 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 36 37 Operationen Operationen Parameter Parameter: Richtung Ein Parameter besteht aus der Angabe von Ein Parameter kann folgende Richtungen haben: Name Typ (optional) Multiplizität (optional) Anfangswert (optional) Richtung Name, Typ, Multiplizität und Anfangswert werden wie bei Attributen gewählt und angegeben 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 38 Operationen 39 Operationen Rückgabetyp Rückgabetyp Gibt den Typ des Werts an, der zurückgegeben wird Rückgabewert vs. Ausgabeparameter: Es kann maximal einen Rückgabewert geben Angabe nach dem Namen mit vorangestelltem : Für Spezifikation der Änderung von Werten mehrerer Objekte durch eine Funktion braucht man Ausgabeparameter Wird weggelassen, falls es keinen Rückgabewert gibt 40 41 Operationen Operationen Getter und Setter Zugriff auf mehrwertige Attribute 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 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): Eine setter-Operation setzt den Wert eines Attributs mittels eines Eingabeparameters neu Prototyp: set<Attributname>(in <neuerWert>) add<Attributname>(in <zusätzlicherWert>) Eine getter-Operation liest den Wert eines Attributs und gibt diesen zurück Prototyp: get<Attributname>(): <Attributtyp> delete<Attributname>(in <veralteterWert>) get<Attributname>(in p:Integer):<Attributtyp> 42 Operationen 43 Operationen Konstruktoren Konstruktoren Konstruktoren sind Operationen zur Erzeugung und Initialisierung von Objekten Konstruktoren initialisieren Attribute durch Zuweisung von Werten 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 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 Operationen Klassenoperationen Beispiel: Student Student Klassenoperationen sind der jeweiligen Klasse zugeordnet und nicht auf ein einzelnes Objekt der Klasse anwendbar Zugriff mittels <Klassenname>.<Operationsname> matrikelnummer:String Adresse:Adresse [0..1] anzahl :Integer =0 {anzahl>=0} ... Angabe wir normale Operationen, allerdings unterstrichen Für den Zugriff auf Klassenattribute Für Berechnungen, die sich auf mehrere Objekte einer Klasse beziehen Student(in matrikelnummer:String) Student(in matrikelnummer:String, in adresse:Adresse) sortieren() getAnzahl():Integer ... 46 Operationen 47 Wie findet man Klassen? Operationen vs. Funktionsaufrufe Dokumentenanalyse: Formulare, Bedienungsanleitungen, Fragebögen, … 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 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, … 48 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 Vorlesung Informatik II Universität Augsburg Sommersemester 2011 Prof. Dr. Robert Lorenz Lehrprofessur für Informatik Eine solche Nachricht ist ein Operationsaufruf 05. UML: Klassendiagramm Der Sender muss mit den eigenen Berechnungen auf die Bearbeitung der aufgerufenen Operation warten 50 Klassendiagramm 1 Assoziationen Im Klassendiagramm werden Klassen und ihre Beziehungen zueinander graphisch dargestellt Assoziationen beschreiben gleichartige Beziehungen zwischen Objekten Ein Klassendiagramm beschreibt das statische Datenmodell des Systems Angestellter ist Vorgesetzter von Angestellter Professor betreut Diplomarbeit Menge besteht aus Elementen Verzeichnis ist ein Dateiobjekt Ein Klassendiagramm definiert einen Namensraum für Klassennamen und Objektnamen Beziehungen können Assoziationen und Generalisierungen sein 2 3 Assoziationen Assoziationen Assoziationen beschreiben gleichartige Beziehungen zwischen Objekten Assoziationen weisen den beteiligten Klassen Multiplizitäten und Rollen zu An einer Assoziation müssen mindestens zwei Objekte beteiligt sein Solche Beziehungen lassen sich in der Regel durch Verben beschreiben können einen beschreibenden Namen besitzen können Navigierbarkeit besitzen können Einschränkungen unterliegen (Datenstruktur-Invarianten) Werden grafisch durch Verbindungslinien zwischen den beteiligten Klassen dargestellt können Eigenschaftswerte haben 4 Assoziationen 5 Assoziationen Multiplizität Rolle Beschreibt Grenzen für die Anzahl von Objekten der anderen Klasse, die mit einem Objekt der betrachteten Klassen in Beziehung stehen können Beschreibt die Funktion oder Aufgabe eines Objekts in einer Beziehung Rollen müssen zugewiesen werden, wenn 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 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 Sonderfälle 0..m,n..*,1..m wie bei Attributen 6 7 Assoziationen Assoziationen Name Navigierbarkeit Beschreibt die Art der Beziehung, in der Regel durch ein Verb. gibt an, ob Objekte einer betrachteten Klasse auf Objekte anderer an der Beziehung beteiligter Klassen zugreifen können Bei binären Assoziationen: <Klassenname> <Assoziationsname> <Klassenname> sollte einen lesbaren Satz ergeben Der Name beschreibt eine Richtung der Beziehung Eine binäre Assoziation kann dabei uni-direktional sein (nur in eine Richtung navigierbar) bi-direktional sein (in beide Richtungen navigierbar) Namen müssen zugewiesen werden, wenn zwischen bestimmten Klassen mehr als eine Assoziation besteht Brauchen Operationen Informationen über assoziierte Objekte? Ja: Navigierbarkeit einfügen Wird in der Mitte der Verbindunglinie angegeben (mit Pfeil für die Lesrichtung bei binären Assoziationen) Wird grafisch durch Pfeilspitzen in Richtung der Navigierbarkeit an Verbindungslinie angegeben 8 Assoziationen 9 Assoziationen Navigierbarkeit Assoziationen: Grafische Darstellung 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 <Klassenname> <Klassenname> n..m *..* <rollenname> <rollenname> ← <assoziationsname> <Klassenname> <Klassenname> Achtung: Im UML-Modell tauchen diese Referenzattribute NICHT auf 10 11 Assoziationen Assoziationen Beispiel: Angestellter ist Vorgesetzter von Angestellter Angestellter Vorgesetzter 1..1 Beispiel: Professor betreut Diplomarbeit Mitarbeiter 1..* Professor 1..1 betreut → betreuer 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 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 Muss zu fachlichen Gegebenheiten passen 12 Assoziationen 13 Assoziationen Verwaltungsoperationen Verwaltungsoperationen: einwertige Beziehungen 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 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> 14 <n..1> <rolle> <Klasse2> 15 Assoziationen Assoziationen Verwaltungsoperationen: mehrwertige Beziehungen Verwaltungsoperationen: bi-direktionale Assoziationen 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> 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! 16 Assoziationen Assoziationen Beispiel: Angestellte, Mitarbeiter und Vorgesetzte Angestellter ... linkMitarbeiter(in a: Angestellter) unLinkMitarbeiter(in a: Angestellter) getLinkMitarbeiter(in n:Integer):Angestellter Vorgesetzter 17 Ist das Modell korrekt? Mitarbeiter 1..* 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: 1..1 Beispiel: Weniger Navigierbarkeit einfacher zu implementieren, aber u.U. eingeschränkte Funktionalität Wichtig: man muss seinen Modellierungsvorschlag begründen können ist Vorgesetzter von → 18 19 Assoziationen Assoziationen Assoziationsklassen Assoziationsklasse: Grafische Darstellung Sind Assoziationen mit Attributen, Operationen und Assoziationen zu anderen Klassen <Klassenname> Assoziationsklassen können in Assoziationen und eine normale Klasse aufgelöst werden (beachte Anpassung der Multiplizitäten und Navigierbarkeiten) <Klassenname> <Assklassenname> Grafisch wie Klassen, durch gestrichelte Linie mit Assoziationsverbindungslinie verbunden 20 Assoziationen Aggregationen Beispiel: Student leiht Buch aus Student Student leiht aus → 0..1 21 0..* 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. Buch Ausleihe Eine der Klassen ist das Ganze, die andere Klasse seine Teile datum zeitraum 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 Ausleihe 1..1 0..* datum zeitraum 1..1 0..1 Buch Grafisch dargestellt durch nicht ausgefüllte Raute am Ende der Verbindungslinie zum Ganzen 22 23 Aggregationen Aggregationen Verwaltungsoperationen Aggregation: grafische Darstellung Dienen der Verwaltung der Teile durch das Ganze Haben andere intuitivere Namen: <Klassenname> insert-Operation entspricht link-Operation remove-Operation entspricht unLink-Operation get-Operation entspricht getLink-Operation besteht aus → ganzes teile <Klassenname> 24 Aggregationen 25 Kompositionen Beispiel: Menge aus Objekten einer Klasse Eine Aggregation ist eine Komposition, wenn ein Objekt nur Teil eines Ganzen sein kann Menge ... insertElemente(in k:<Klasse>) removeElemente(in k:<Klasse>) getElemente(in pos:Integer):<Klasse> Wird das Ganze gelöscht, werden automatisch auch seine Teile gelöscht Grafisch dargestellt durch ausgefüllte Raute am Ende der Verbindungslinie zum Ganzen 0..* elemente Verwaltungsoperationen haben andere intuitivere Namen: add-Operation entspricht link-Operation delete-Operation entspricht unLink-Operation get-Operation entspricht getLink-Operation 0..* <Klasse> 26 27 Kompositionen Kompositionen Komposition: grafische Darstellung <Klassenname> Beispiel: Verzeichnis besteht aus Dateiobjekten 0..1 ganzes teile Verzeichnis ... addElemente(in d:<Dateiobjekt>) deleteElemente(in d:<Dateiobjekt>) getElemente(in p:Integer):<Dateiobjekt> <Klassenname> 0..1 elemente 0..* Dateiobjekt Irgendwas passt hier aber noch nicht: Verzeichnisse sind doch auch Dateiobjekte!? Modell (noch) unvollständig/ungenau (Verbesserung später) 28 Mehrwertige Assoziationen Generalisierung Mehrwertige Assoziationen beschreiben Beziehungen zwischen Objekten von drei oder mehr verschiedenen Klassen <Klassenname> 29 <Klassenname> 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) <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 31 Generalisierung Generalisierung Jedes Objekt der sog. Unterklasse ist ein Objekt der sog. Oberklasse 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) 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 Grafisch dargestellt durch eine geschlossene, nicht ausgefüllt Pfeilspitze am Ende der Verbindungslinie zur Oberklasse Attribute, Operationen und Assoziationen der Oberklasse werden nicht noch einmal für die Unterklasse angegeben 32 Generalisierung 33 Generalisierung Generalisierung: grafische Darstellung Beispiel: Dateien und Verzeichnisse sind Dateiobjekte Dateiobjekt <Oberklassenname> <Unterklassenname> Datei <Unterklassenname> 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) 34 35 Generalisierung Generalisierung Beispiel: Dateien und Verzeichnisse sind Dateiobjekte Beispiel: Dateien und Verzeichnisse sind Dateiobjekte Dateiobjekt Dateiobjekt 0..* name 0..* ... kopieren() erstelldatum Datei Verzeichnis groesse freigabe Gemeinsame und spezielle Attribute Datei Verzeichnis ... ... speichern() freigeben() Gemeinsame und spezielle Operationen 36 Generalisierung 37 Generalisierung Vererbungsprinzip Substitutionsprinzip Die Oberklasse vererbt ihre Attribute, Operationen und Beziehungen an die Unterklasse Objekte von Unterklassen können jederzeit als ein Objekt einer Oberklassen verwendet werden Ein Objekt der Unterklasse besitzt alle Attribute der Oberklasse Entspricht einer Typausweitung 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 39 Generalisierung Generalisierung Objekt-Verantwortlichkeitsprinzip Top-Down-Entwurf einer Vererbungshierarchie: Jede Klasse definiert einen Verantwortlichkeitsbereich. Bildung von Unterklassen durch Addition von Attributen, Operationen und Assoziationen zu einer Klasse Attribute und Operationen werden entsprechend dem Verantwortlichkeitsbereich einer möglichst speziellen Klasse in einer Vererbungshierarchie zugeordnet Beispiel: Ein Tutor ist eine Spezialisierung eines Studenten 40 Generalisierung 41 Generalisierung Bottom-Up-Entwurf einer Vererbungshierarchie: Prinzip abstrakter Klassen 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 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 Generalisierung Prinzip abstrakter Klassen Prinzip abstrakter Operationen Klassen, von denen keine Objekte erzeugt werden können oder sollen, heißen abstrakte Klassen Werden in der betrachteten Klasse nicht implementiert, sondern nur vereinbart durch Angabe des Prototypen (Signatur) Abstrakte Klassen können konkrete Operationen enthalten Durch abstrakte Operationen werden gemeinsame Signaturen für Unterklassen definiert. 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 In der Implementierung müssen die Unterklassen die abstrakte Operation durch konkrete Operationen überschreiben Klassen mit abstrakten Operationen müssen auch abstrakt sein 44 Generalisierung Generalisierung Beispiel: Dateien und Verzeichnisse sind Dateiobjekte <<abstract>> Dateiobjekt ... getName() kopieren() {abstract} Datei ... kopieren() 45 Polymorphismus: Unterklassen können Operationen von Oberklassen überschreiben (redefinieren) und unterschiedlich implementieren 0..* Derselbe Operationsaufruf für Objekte verschiedener Klassen einer Vererbungshierarchie führt zur Ausführung unterschiedlicher Operationen (Aufruf für jedes Dateiobjekt o: o.kopieren()) Verzeichnis ... 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) Implementierung abstrakter Operationen in Unterklassen 46 47 Generalisierung Generalisierung Spätes Binden: Überschreiben vs. Überladen Beim Übersetzen des Programms muss für ein Objekt der Oberklasse noch nicht bekannt ist, zu welcher Unterklasse es gehört. Überladen: Eine Operation kann innerhalb einer Klasse öfter mit verschiedenen Signaturen vorkommen (Operation println() der Klasse PrintStream) Erst zur Laufzeit wird die Operation an das Objekt gebunden. Überschreiben: Eine Operation einer Oberklasse kann von einer Operation einer Unterklasse mit gleicher Signatur überschrieben werden Einheitlicher Aufruf für potentiell unterschiedliche Objekte Dadurch werden Mehrfachauswahlen vermieden Beispiel: for all o in list: o.kopieren() 48 Generalisierung 49 Generalisierung Mehrfachvererbung Überschreiben von Attributen Grundsätzlich können Objekte von mehreren Klassen erben (mehrere Oberklassen haben) 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 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 Schnittstellen Vorteile: Eine Schnittstelle ist eine Sammlung von abstrakten Operationen und konstanten Klassenattributen 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 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 Bei Hinzufügen/Änderung einer Oberklasse müssen u.U. auch alle Unterklassen verändert werden 52 Schnittstellen 53 Schnittstellen Klassen können Schnittstellen implementieren Schnittstellen-Prinzip Dazu implementieren sie alle spezifizierten Operationen konkret und können die konstanten Klassenattribute benutzen In der Schnittstelle spezifizierte Operationen können für jede implementierende Klasse auf dieselbe Weise aufgerufen werden (Schnittstellen können als Datentyp benutzt werden) 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 55 Schnittstellen Schnittstellen Grafische Darstellung Beispiel: Durchlaufen von dynamischen Feldern (Klassenbibliothek: Iteratormuster) <<interface>> <Schnittstellenname> <Klassenname> <<interface>> Iterable<E> iterator():Iterator<E> <<interface>> Iterator<E> hasNext():boolean next():<E> remove() <Klassenname> Vector ArrayList ... 56 57 Sichtbarkeiten 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) Für Klassen (In welchen anderen Klassen stehen Objekte der Klasse zur Verfügung): + überall sichtbar - innerhalb des eigenen Pakets # nicht benutzbar ~ nicht benutzbar Wird vor dem Namen angegeben 58 59 Sichtbarkeiten Sichtbarkeiten Für Attribute (Objekte welcher Klassen können auf den Attributwert ohne Operation zugreifen): Für Operationen (Objekte welcher Klassen können die Operation aufrufen): + überall sichtbar + überall sichtbar - sichtbar in der Klasse - sichtbar in der Klasse # sichtbar innerhalb der Klasse und allen Unterklassen # sichtbar innerhalb der Klasse und allen Unterklassen ~ sichtbar im Paket ~ sichtbar im Paket 60 Sichtbarkeiten Sichtbarkeiten Für Assoziationen: Angabe für Rollen + überall sichtbar - sichtbar in der Klasse # sichtbar innerhalb der Klasse und allen Unterklassen ~ sichtbar im Paket 61 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 62 63 Sichtbarkeiten Sichtbarkeiten Beispiel: Menge von Objekten einer Klasse implementiert als einfach verkettete Liste Beispiel: Menge von Objekten einer Klasse implementiert als einfach verkettete Liste: Geheimnisprinzip? + Liste 0..1 -next + Knoten 1..1 + Knoten 0..1 -start + + + + + + + + + Liste -size:Integer =0 -wert + <Klasse> 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>) ... 64 Containerklassen 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 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 Containerklassen Grafische Darstellung Beispiel: Professoren + <Containerklasse> + ProfessorenContainer - unique :<Containerklasse> =null - unique :ProfessorenContainer =null - <Containerklasse>() + instance(): <Containerklasse> + + + + 1..1 ProfessorenContainer() instance(): ProfessorenContainer addProfessor(in p:Professor) deleteProfessor(in p:Professor) getProfessor(in p:Integer):Professor 1..1 - alleObjekte - alleProfessoren 0..* + <Klasse> 0..* + Professor 68 Containerklassen 69 Containerklassen Containerklassen erhalten die Klassenattribute und –operationen der verwalteten Klasse als Objektattribute und -operationen Beispiel: Klassenattribute und –operationen <Containerklasse> <Klasse> <Attribut> <Containerklasse> <Attribut> <Klasse> <Operation> anzahl 1..1 <Operation>() - alleObjekte anzahl getAnzahl() 1..1 getAnzahl() 0..* - alleObjekte <Klasse> 0..* <Klasse> 70 71 Muster Muster sind generische Lösungen für wiederkehrende Entwurfsprobleme Vorlesung Informatik II Universität Augsburg Erhöhen die Standardisierung und damit die Qualität und Wartbarkeit des Entwurfs und der Software Sommersemester 2011 Muster werden durch Klassendiagramme beschrieben Prof. Dr. Robert Lorenz Beispiel: Singletonmuster, falls es höchstens ein Objekt einer Klasse geben soll Lehrprofessur für Informatik In der Praxis: Vielzahl von Mustern In dieser Vorlesung: 2-3 exemplarische Muster 06. Java: Von UML nach Java 1 72 Operator instanceof Inhalt Für die meisten Elemente und Konzepte eines Klassendiagramms gibt es Entsprechungen in Java Erlaubt die Überprüfung, ob ein Objekt von einer bestimmten Klasse ist in der folgenden Form Wir werden jetzt die Syntax dieser Entsprechungen lernen <Objekt> instanceof <Klasse> Angenehmerweise bleibt die Semantik erhalten, wir haben bei der UML-Modellierung also schon die halbe Programmierarbeit erledigt Wert dieses Ausdrucks ist vom Typ boolean Manchmal hat man allerdings Implementierungsalternativen Wir beginnen mit einigen API-Grundlagen. 2 3 Klasse Object Klasse Object Jede Klasse erbt (ist eine Spezilisierung) von der Klasse Object: public boolean equals(Object obj) Konsequenzen: Definiert die Gleichheit zweier Objekte Voreinstellung: Identität (Zeiger auf dasselbe Objekt) 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 Die Klasse String überschreibt diese Methode schon, s.d. zwei Zeichenketten tatsächlich auf gleichen Inhalt überprüft werden Wichtige Methoden der Klasse Object: public boolean equals(Object obj) public String toString() 4 Klasse Object 5 Klasse Object public boolean equals(Object obj) 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 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 Klasse Object public String toString() public String toString() Definiert die textuelle Darstellung eines Objekts (als eine Zeichenkette) Beispiel: Für Studenten wird Name und Matrikenummer ausgegeben Jede Klasse sollte diese Methode überschreiben class Student { ... public String toString(){ return “Matrikelnummer: “ + matnummer + “\n Name: “ + name; } ... 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 Containerklassen 9 Containerklassen Grundsätzliche Typen: Beispielklassen: 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 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 Klasse Vector Containerklassen Beispielklassen: Exemplarisch besprechen wir die Klasse Vector<T>: HashSet Menge Iterationsreihenfolge ist ungeordnet und nicht reproduzierbar repräsentiert ein dynamisches Feld von Objekten Hashtable Abbildung Zugriff auf Elemente wie bei Feldern Elemente von primitiven Datentypen können nicht verwaltet werden (hier helfen die Hüllklassen) T ist der Datentyp der Elemente (Angabe ist optional). Ohne Angabe von T Verwaltung von beliebigen Objekten 12 Klasse Vector 13 Klasse Vector Einige Operationen der typisierten Version Vector<T>: Einige Operationen der typisierten Version Vector<T>: void addElement(T obj) hängt obj als letztes Element an int indexOf(T elem) liefert den Index des ersten Elements e mit e.equals(elem) void insertElementAt(T obj, int index) fügt obj an Position index ein und verschiebt andere Elemente boolean removeElement(T obj) entfernt das erste Auftreten von obj T elementAt(int index) liefert das Element an Stelle index Alternative: T get(int index) 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! void setElementAt(T obj, int index) ersetzt das Element an Position index durch obj 14 15 Sichtbarkeiten + entspricht public - entspricht private # entspricht protected ~ entspricht package 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 16 Attribute 17 Attribute Angabe von Attributen in folgender Form: Möglichkeiten der Initialisierung von Attributen: Explizit in der Deklaration <Sichtbarkeit> [static] <Datentyp> <Name> [=<Wert>] Explizit im Konstruktor Angabe von static für Klassenattribute Implizit durch voreingestellten Wert Angabe von =<Wert> für Anfangswerte Initialisierung von Klassenattributen <Datentyp> abhängig von Multiplizität: Explizit in der Deklaration ?..1 <Datentyp> entspricht UML-Datentyp ?..m <Datentyp> entspricht UML-Datentyp-Feld (m>1) ?..* <Datentyp> entspricht einer Java-Containerklasse 18 In separatem Block static { ... } 19 Objekte Konstruktoren Auswertung von Objekten: Angabe von Konstruktoren in folgender Form: <Sichtbarkeit> <Klassenname>(<Parameter>){<Rumpf>} Objekte primitiven Typs werden als Wert der Speicherstelle ausgewertet UML-Konstruktoren werden Java-Konstruktoren Konstruktoren können überladen werden Objekte eines Referenztyps werden als Zeiger auf die Speicherstelle ausgewertet Ein Ausdruck der Form <objekt>.<attribut> wird als Wert des Attributs ausgewertet (automatische Dereferenzierung) 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 20 21 Konstruktoren Konstruktoren Das Schlüsselwort this: Aufruf von Konstruktoren Mit this(<Werte>) kann in einem Konstruktor auf einen anderen Konstruktor zugegriffen werden Aufruf durch Ausdruck new <Klassenname>(<Werte>) Erzeugung eines Objekts Ausdruck wird als Zeiger auf dieses Objekt ausgewertet Mit this.<attribut> kann auf überschriebene Attribute zugegriffen werden Verwendung in beliebigen Ausdrücken und auch als Eingabeparameter von Operationen this kann in Operationsrümpfen als Referenz auf das aufrufende Objekt benutzt werden (Beispiel später) 22 23 Konstruktoren Operationen Implementierung von Konstruktoren Angabe von Operationen in folgender Form: class <Klasse>{ private <Typ> <Attribut>; ... <Sichtbarkeit>[static][abstract]<Rückgabetyp><Name>(<Parameter>){ <Rumpf> } UML-Operationen werden Java-Operationen (alle Verwaltungsoperationen für Attribute und Assoziationen usw.) public p <Klasse>(<Typ> <Attribut>){ this.<Attribut>=<Attribut>; } Gibt es keinen UML-Rückgabetypwert, so ist der JavaRückgabetyp void public p <Klasse>(<Typ> <Attribut>,...){ this(<Attribut>); ... } Angabe von abstract bei abstrakten Operationen Abstrakte Operationen haben keinen Rumpf } Angabe von static bei Klassenoperationen 24 Operationen 25 Operationen Im Operations-Rumpf Aufruf von Operationen Werte primitiven Datentyps werden nach dem Call-by-ValuePrinzip übergeben Aufruf von normalen Objekt-Operationen durch Ausdruck <objekt>.<operation>(<Werte>) (vorher muss das Objekt <objekt> deklariert und erzeugt werden) 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 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 Operationen Implementierung von Gettern und Settern Implementierung von Gettern und Settern Einfachste Form: Zusätzliche Fehlerbehandlung: Überprüfung Dateninvarianten bei Settern (ungültige Werte) class <Klasse>{ private <Typ> <Attribut>; ... Beispiel: Namen beginnen mit Großbuchstaben und haben eine Länge zwischen 3 und 20 Buchstaben public p <Typ> get<Attribut>(){ return <Attribut>; } Kontrolle, ob Wert vorhanden (bei optionalen Attributen) bei Gettern public p void set<Attribut>(<Typ> <Attribut>){ this.<Attribut>=<Attribut>; } } 28 29 Operationen Operationen Implementierung von Gettern und Settern Implementierung bei mehrwertigen Attribute (einfachste Form): Verhalten bei Auftreten eines Fehlers: Aktion nicht ausführen Anzeige über Rückgabewert (Fehlerbehandlung durch den Aufrufer) oder Fehlermeldung 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>); } 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 31 Operationen Operationen Implementierung der Verwaltung mehrwertiger Attribute: Implementierung der Verwaltung von Objektbeziehungen: Zusätzliche Fehlerbehandlung: später Ü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 Spezialisierung 33 Spezialisierung Angabe von Spezialisierungen in folgender Form: Implementierung: Benutzung von super public class <Klasse2>{ private <Typ2> <Attribut2>; public <Klasse2>(<Typ2> <Attribut2>){...} } 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 public class <Klasse1> extends <Klasse2>{ private <Typ1> <Attribut1>; public <Klasse1>(<Typ1> <Attribut1>,<Typ2> <Attribut2>){ super(<Attribut2>); ... } } 35 Spezialisierung Uni-direktionale Assoziationen Angabe von einwertigen Assoziationen in folgender Form: Implementierung: Polymorphismus public class <Klasse1> extends <Klasse2>{ ... } <Klasse1> ?..1 - <rolle> <Klasse2> public class <Klasse1>{ private <Klasse2> <rolle>; ... } 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 Beziehung über den Rollennamen als Attribut einbinden in Richtung der Navigierbarkeit Zugriff über öffentliche Verwaltungsoperationen wie im Klassendiagramm spezifiziert 36 Uni-direktionale Assoziationen Uni-direktionale Assoziationen Verwaltungeoperationen für einwertige Assoziationen <Klasse1> ?..1 - <rolle> 37 Angabe von mehrwertigen Assoziationen in folgender Form: <Klasse2> <Klasse1> 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>; } } ?..* - <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 38 39 Uni-direktionale Assoziationen Uni-direktionale Assoziationen Verwaltungsoperationen für mehrwertige Assoziationen ?..* - <rolle> <Klasse1> Zusätzlich bei Verwaltungsoperationen zu beachten ist die Fehlerbehandlung: <Klasse2> Dateninvarianten sicherstellen in link- und unlink-Operationen 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);} } 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] 40 Bi-direktionale Assoziationen Bi-direktionale Assoziationen Angabe: Beziehung über die Rollennamen als Attribut einbinden für beide Klassen (wie uni-direktional in beide Richtungen) - <rolle1> - <rolle2> Verwaltungsoperation link exemplarisch im beiderseits einwertigen Fall: <Klasse1> Link- und unlink-Operationen beider Klassen stellen aus Symmetriegründen Beziehung in beide Richtungen her <Klasse1> 41 <Klasse2> Achtung: Überprüfe, ob beteiligte Objekte nicht schon in anderer Beziehung: in diesem Fall unlink für alte Beziehung notwendig 42 - <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 Aggregation und Komposition Verwaltungsoperationen allgemeiner Fall: <Klasse1> - <rolle1> - <rolle2> Sind Spezialfälle uni-direktionaler Assoziationen Implementierung wie geschildert über Attribut für Rollennamen <Klasse2> Verwaltungsoperationen mit anderen Namen, aber ähnlicher Funktionalität 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 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);} } 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); ... 46 47 Schnittstellen Schnittstellen Angabe von Schnittstellen in folgender Form: Die implements-Beziehung: interface <Schnittstelle>{<Rumpf>} 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 48 Schnittstellen Schnittstellen Beispiel: Iterator-Muster (Klassenbibliothek) Beispiel: Iterator-Muster (Klassenbibliothek) <<interface>> Iterable<E> iterator():Iterator<E> <<interface>> Iterable<E> <Klasse>Container <Klasse>Container Vector Vector Damit läßt sich der Container unabhängig von seiner Implementierung durchlaufen public class <Klasse>Container implements Iterable<Klasse> { private Vector<Klasse> alle<Klasse> = new Vector<Klasse>(); ... public Iterator<Klasse> iterator(){ return alle<Klasse>.iterator(); } } Iterator<Klasse> it = <Klasse>Container.iterator(); while(it.hasNext()){ <Klasse> o = it.next(); ... 50 51 Schnittstellen Pakete Beispiel: Ereignisbehandlung (nächstes Kapitel) Einbindung von Klassen in Pakete zu Beginn einer Datei: package <meinPaket>; <Klassendefinition> Import und Zugriff auf Klassen anderer Pakete zu Dateibeginn import <paketname>.<Klasse>; 52 53