Eigentlich ein Verkehrsschild -- schaut aber wie UML aus!? Modellierung von Struktur OOPM, Ralf Lämmel
733 Motivation: Wir wollen die Struktur für eine Anwendung im Personalwesen modellieren. MSFT Firma HR Dev Abteilungen Unter- abteilungen VB C# Angestellte Paul Erik Ander
734 Ein Klassendiagramm für eine Anwendung im Personalwesen Verwendung von Komposition (Teil-Ganzes-Beziehung)
735 Beziehungen im OO Paradigma Auf Objektebene Verknüpfungen zwischen Objekten Auf Typebene (Klassen / Schnittstellen) Generalisierung Eine Klasse spezialisiert eine andere Klasse. Ein Schnittstelle spezialisiert eine andere Schnittstelle. Eine Klasse realisiert eine Schnittstelle. Mehrfachvererbung Assoziationen Modellierung von Verknüpfungen auf Typebene
736 Fahrplan Relevante Sprachmittel in Java Klassenbeziehungen UML-Notation für Beziehungen in Klassendiagrammen Abwägung von Vererbung vs. Komposition Abbildung von UML s Beziehungen auf Java
737 Ein Beispiel Eine Klasse für Zähler (Counter) Zustand Zählerstand Verhalten Zähler erhöhen ( step ) Zählen ablesen ( read ) Zähler zurücksetzen ( reset ) Siehe Package oo.counter und Unterpackages
738 /** * A simple class of counters */ public class BasicCounter { /** Private state of the counter */ private int count = 0; /** Increment the counter */ public void step() { count++; /** Return the value of the counter */ public int read() { return count; /** Reset the counter to zero */ public void reset() { count = 0;
739 Veränderte Anforderung (Realisierung mit Klassenvererbung) Zähler mit Grenze ( limit ) Zustand Limit Modifiziertes Verhalten Zähler erhöhen ( step )
740 /** * A counter whose count is limited */ public class LimitedCounter extends BasicCounter { private int limit; /** Construct a limited counter from the limit */ public LimitedCounter(int i) { limit = i; /** Stop stepping when the limit is reached */ public void step() { if (read() < limit) super.step(); Aufruf der Implementation der Oberklasse
741 Veränderte Anforderung (Realisierung mit Klassenvererbung) Zähler mit Erinnerung ( recall ) Zustand Geretteter Wert ( snap ) Zusätzliches Verhalten Retten des Wertes ( mark ) Erinnern ( recall )
742 /** * A counter with recall */ public class RecallCounter extends BasicCounter { private int snap = read(); /** Store the counter state until later */ public void mark() { snap = read(); /** Reset the counter for recall */ public void recall() { count = snap; Oops! Unzulässiger Zugriff auf count!
743 /** * A simple class of counters */ public class BasicCounter { /** Protected state of the counter */ protected int count = 0; Gewährung von Zugriff für Unterklassen /** Increment the counter */ public void step() { count++; /** Return the value of the counter */ public int read() { return count; /** Reset the counter to zero */ public void reset() { count = 0;
744 Beschränkung der Veerbung Finale Klasse Kann nicht spezialisiert werden Beschränkt Typsubstitution Finale Methode Kann nicht überschrieben werden Beschränkt Verhaltensänderungen
745 /** * A counter that cannot be extended any further */ public final class FinalCounter extends BasicCounter {
746 Variation im OO Entwurf Identifikation einer Schnittstelle für Zähler Abstraktion von jeglicher Implementation Warum? Lässt die Oberklasse offen Nicht so wichtig für triviale Zähler! Interessant für komplexere Datenstrukturen
747 /** * The shared interface of counters */ public interface Counter { /** Increment the counter */ void step(); /** Return the value of the counter */ int read(); /** Reset the counter to zero */ void reset();
748 /** * A simple class of counters */ public class BasicCounter implements Counter { // Private state of the counter protected int count = 0; /** Increment the counter */ public void step() { count++; /** Return the value of the counter */ public int read() { return count; /** Reset the counter to zero */ public void reset() { count = 0;
749 Variation im OO Entwurf Wieder Zähler mit Grenze mit Wiederverwendung aber ohne Vererbung Benutzung von Assoziation Verknüpfung zu Zähler ohne Grenze Delegation von Nachrichten Warum? Nicht so wichtig für triviale Zähler! Nötig wenn Oberklasse anderweitig feststeht Ermöglicht Dekoration & Komposition von Verhalten
750 /** * A counter whose count is limited */ public class LimitedCounter implements Counter { private BasicCounter inner = new BasicCounter(); private int limit; /** Construct a limited counter from the limit */ public LimitedCounter(int i) { limit = i; /** Return the value of the counter */ public int read() { return inner.read(); Delegation /** Reset the counter to zero */ public void reset() { inner.reset(); Delegation /** Stop stepping when the limit is reached */ public void step() { if (read() < limit) inner.step(); Bedingte Delegation
751 Variation im OO Entwurf Wieder Zähler mit Erinnerung mit Wiederverwendung aber ohne Vererbung Benutzung von Assoziation Verknüpfung zu Zähler ohne Erinnerung Delegation von Nachrichten
752 public class RecallCounter implements Counter { private BasicCounter inner = new BasicCounter(); private int snap = inner.read(); /** Increment the counter */ public void step() { inner.step(); /** Return the value of the counter */ public int read() { return inner.read(); /** Reset the counter to zero */ public void reset() { inner.reset(); /** Store the counter state until later */ public void mark() { snap = read(); /** Reset the counter for recall */ public void recall() { inner.count = snap; Oops! Unzulässiger Zugriff auf count! Oops! protected tut es nicht!
753 /** * A simple class of counters */ public class BasicCounter implements Counter { // Package-private state of the counter /* default */ int count = 0; Gewährung von Zugriff für Klassen im Package /** Increment the counter */ public void step() { count++; /** Return the value of the counter */ public int read() { return count; /** Reset the counter to zero */ public void reset() { count = 0;
754 Zugriffskontrollen public Zugriff darf von überall erfolgen private Zugriff nur innerhalb der Klasse protected Zugriff in der Klasse und Unterklassen default Zugriff überall innerhalb des Packages Synonyme: friendly und package private
755 Beziehungen im OO Paradigma Auf Objektebene Verknüpfungen zwischen Objekten Auf Typebene (Klassen / Schnittstellen) Generalisierung Eine Klasse spezialisiert eine andere Klasse. Ein Schnittstelle spezialisiert eine andere Schnittstelle. Eine Klasse realisiert eine Schnittstelle. Mehrfachvererbung Assoziationen Modellierung von Verknüpfungen auf Typebene
756 Einfach- & Mehrfachvererbung Erbt eine Klasse nur von einer anderen Klasse, so spricht man von Einfachvererbung. Sind es mehrere Klassen, von denen geerbt wird, so bezeichnet man dies mit Mehrfachvererbung.
757 Mehrfachvererbung Zulässig in UML und C++ u.a. Unklarheiten / Probleme / Risiken Direkte Konflikte (siehe paymeal) Indirekte Konflikte (siehe name) Mehrfachvererbung in Java Nicht zulässig für Klassen Zulässig für Schnittstellen
758 Mehrfachvererbung in UML (ein weiteres Beispiel)
759 Eine Klasse kann mehrere Schnittstellen implementieren.
760 Beziehungen im OO Paradigma Auf Objektebene Verknüpfungen zwischen Objekten Auf Typebene (Klassen / Schnittstellen) Generalisierung Eine Klasse spezialisiert eine andere Klasse. Ein Schnittstelle spezialisiert eine andere Schnittstelle. Eine Klasse realisiert eine Schnittstelle. Mehrfachvererbung Assoziationen Modellierung von Verknüpfungen auf Typebene
761 Assoziationen Allgemeine Assoziation Teil-Ganzes Beziehungen Aggregation Komposition
762 Allgemeine Assoziationen Zwei Klassen gehen eine Beziehung ein. Modelliert Verbindungen zwischen Instanzen Multiplizität der Verbindung ist festzulegen Gerichtete Verbindungen sind nur einseitig navigierbar Beispiel Ein Konto hat einen (1) zugeordneten Kunden. Ein Kunde besitzt beliebig viele (0..*) Konten.
763 Teile-Ganzes-Beziehungen Siehe Package oo.shapes.awtish Aggregation Alle Multiplizitäten sind zulässig Unausgefüllte Raute am Ende des Ganzen Komposition Stärkere Form der Aggegration Multiplizitäten 1 und 0..1 zulässig für das Ganze Ausgefüllte Raute am Ende des Ganzen Beispiel Eine Abbildung besteht aus beliebig vielen Formen.
764 Unterscheidung von Aggregation und Komposition Betrachte die Beziehung zwischen Klassen für Fahrzeuge und Motoren. Ein Motor ist definitiv ein Teil des Fahrzeugs. Nehmen wir weiterhin an, dass die Klassen technische Entwürfe modellieren. Dann kann ein Motor Teil mehrerer Fahrzeuge sein. Aggregation ist adäquat. Komposition wäre stattdessen adäquat, wenn die Klassen physische Fahrzeuge (und deren Komposition aus echten Teilen) modellieren. Jedes Teil kann dann nur einmal verwendet werden.
765 Abwägung zwischen Generalisierung und Assoziation Wäre hier denn vielleicht Komposition anstatt allgemeiner Assoziation angebracht?
766 Kombination aus Generalisierung und Assoziation
767 Java-Implementation von UML-Assoziationen Variationen Gerichtet und ungerichtet Multiplizitäten 0..1, 1, 0..*, 1..* Allgemein vs. Aggregation (Komposition) (Assoziationsklassen (Assoziationen mit Attributen)) (Mehrfachgeneralisierungen (für Klassen)) Siehe Package oo.assoc und Unterpackages. Wir werden die (wenigen) speziellen Herausforderungen von Aggregation nicht besprechen. Wir werden auch gar nicht Implementationsstrategien für mehrfache Generalisierung (Mehrfachvererbung) besprechen.
768 0..1 Modell Jede Person hat möglicherweise eine Residenz. Jede Residenz beherbergt beliebig viele Personen. Navigation ist nur von Person nach Residenz vorgesehen. Implementation Klasse Person hat Feld vom Typ Residence. Das Feld darf legal den Wert null annehmen.
769 /** * A person with an optional residence */ public class Person { private Residence residence; public Residence getresidence() { return residence; public void setresidence(residence residence) { this.residence = residence; /** * A residence... */ public class Residence {...
770 1 Modell Jede Person hat genau eine Residenz. Sonst wie vorher. Implementation Konstruktion einer Person benötigt eine Residenz. Parameter des Konstruktors Erzeugen des Residenzobjektes Gestatten einer zeitweiligen Inkonsistenz
771 Jede Person hat genau eine Residenz. Überprüfung des Parameterkonstruktors public class Person { private Residence residence; /** Construction requires a residence */ public Person(Residence residence) { if (residence==null) throw new IllegalArgumentException(); setresidence(residence); Vordefinierte Ausnahmeklasse...
772 Ableitungsposition von IllegalArgumentException
773 0..* Modell Jede Person hat beliebig viele Residenzen. Sonst wie vorher. Implementation Das Feld für die Residenzen ist von einem Container-Typ.
774 Hinzufügen einer Verknüpfung public class Person { private List<Residence> residences = new LinkedList< Residence >(); public void addresidence(residence r){ residences.add(r); public class Residence {...
775 ungerichtet Modell Navigation von Residenzen nach Personen nun zulässig. Implementation add/remove-operation werden beidseitig angewandt.
776 public class Person { Hinzufügen einer Verknüpfung: gegenseitiger Aufruf private List<Residence> residences = new LinkedList< Residence >(); public void addresidence(residence r){ residences.add(r); r.addperson(this); Oops! Endlosrekursion! public class Residence { private List<Person> persons = new LinkedList<Person>(); public void addperson(person p){ persons.add(p); p.addresidence(this);
777 public class Person { Hinzufügen einer Verknüpfung: entfernte Container-Manipulation private List< Residence > residences = new LinkedList< Residence >(); public void addresidence(residence r){ residences.add(r); r.persons.add(this); Oops! Unerlaubter Zugriff public class Residence { private List<Person> persons = new LinkedList<Person>(); public void addperson(person p){ persons.add(p); p.residences.add(this);
778 public class Person { Hinzufügen einer Verknüpfung: Verwendung der Paketsichtbarkeit /* default */ List< Residence > residences = new LinkedList< Residence >(); public void addresidence(residence r){ residences.add(r); r.persons.add(this); Gibt es weitere Lösungsideen? public class Residence { /* default */ List<Person> persons = new LinkedList<Person>(); public void addperson(person p){ persons.add(p); p.residences.add(this);
Zusammenfassung Struktur wird mit UML s Klassendiagrammen modelliert. Struktur wird mit Java s Klassen implementiert. Man muss Vererbung vs. Objektkomposition abwägen. Man muss Sichtbarkeit regeln. Ausblick Syntax und Semantik von Programmiersprachen Verhaltensmodellierung mit UML...
Assoziationsklassen (Assoziationen mit Attributen) (C) Ralf Lämmel, OOPM, Universität Koblenz-Landau 780 Für das Selbststudium bzw. für die Besprechung in Übung/Praktikum.