Das laufende Beispiel: verschiedene „Zettel“ • Ein „Zettel“ hat ähnlich einer Karteikarte eine Überschrift (kurz: „Titel“) und einen „Inhalt“. Im einfachsten Fall sind Titel und Inhalt beides Zeichenreihen. Kapitel 2: OO Grundlagen 2.1 Objekte „zum Leben erwecken“ (und Grundmechanismen verstehen) 2.2 Statische Elemente nutzen & vererben 2.3 Kooperation über Interfaces • Zettel kann man zählen und mit „Seriennummern“ veredeln. Dann ähneln sie Banknoten oder Reisepässen. • Auf Zettel kann man Eintragungen vornehmen, überschreiben, wieder rückgängig machen, erneut beschreiben ... ¾ Die Programme dieses Kapitels demonstrieren anhand dieser Anwendungsbeispiele die wichtigsten OO Konzepte. ¾ Da praktisch weder Kontrollstrukturen noch Datenstrukturen vorkommen, zeigen die Beispiele ausschließlich OO Elemente und ihre Verwendungsmöglichkeiten. Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K2 - 1 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Zettel-Objekte haben konkret • einen Titel und einen Inhalt (hier Zeichenketten) • einen Konstruktor, der einen Zettel mit gegebenem Titel und Inhalt herstellt • „getter“ und „setter“ für den Inhalt (der Titel ist damit von außen nicht zu verändern) • eine „toString()“-Methode Aus Gründen der Beschreibungsökonomie modelliert man nicht einzelne Objekte, sondern Objektarten, d.h. „Klassen“ von Objekten. Zu modellieren sind dabei: • der „Zustand“ durch geeignete Exemplarvariablen („Attribute“), die in der Regel „privat“, d.h. von aussen unsichtbar sind; • mindestens eine „Konstruktormethode“ zum Erschaffen und Initialisieren von Objekten der Klasse; Zettel • öffentliche („public“) „getter“- und „setter“-Methoden zum Zugriff auf die Attribute, soweit freizugeben; - titel : String - inhalt : String • eine „toString()“-Methode, mit der für Testzwecke der Inhalt des Objekts in lesbarer Form dargestellt werden kann; + Zettel(String,String) + getInhalt() : String + setInhalt(String) : void + toString() : String • als Rest des Protokolls ggfs weitere, klassenspezifische Methoden. Objektoiertierte Programmierung K2 - 3 „toString()“-Methode zur Darstellung Objektoiertierte Programmierung K2 - 4 – elementare Werte (int, char, boolean o.ä.) – oder Objekt-Referenzen (vgl. Ada "access types"), aber niemals Objekte selbst!! public static void main(String[] args) { • Parameter werden stets "per value" übergeben: – beim Aufruf werden die in den aktuellen Parametern Zur Übernahme von Kommandozeilenparametern vorliegenden Referenzen in die formalen Parameter (Variablen) kopiert; – am Ende des Methodenaufrufs werden die formalen Parameter gelöscht (also nicht zurückgegeben!!); • Die „main()-Methode“ kann in einer eigenen Testklasse stehen oder auch in der zu testenden (bzw. auszuführenden) Klasse. ¾ die Inhalte eines Parameterobjekts / Methodenempfängers können verändert werden, nicht aber seine Identität (der Referenz-Wert)! • Die „main()-Methode“ erzeugt Testobjekte per Konstruktoraufruf: • Zettel meiner = new Zettel("z","z-Inhalt") Objektoiertierte Programmierung Zugriff auf Inhalt mit „getter“/“setter“ • Variablen enthalten entweder • Die „main()-Methode“ hat immer den gleichen Rahmen: Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Ein Konstruktor Java: Variablen, Objekte und Parameter • „Eine Klasse ausführen“ heißt immer: ihre „main()-Methode“ starten. } Zwei Exemplarvariablen Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Programme ausführen: die „main()“-Methode .... K2 - 2 Die Zettel-Klasse in UML und Java 2.1 Objekte „zum Leben erwecken“ Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K2 - 5 Die Pseudovariable this bezeichnet den Methodenempfänger. Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Seite 1 Objektoiertierte Programmierung K2 - 6 Java: Object, Casts und Clones 2.2 Statische Elemente nutzen & vererben • "Object" heißt die Wurzelklasse der Vererbungshierarchie. => Jedes Objekt ist ein spezielles Object-Exemplar. Es gibt zweierlei „statische“ Elemente: • analog zu den Exemplarvariablen, die spezifisch für Objekte sind, die „Klassenvariablen“ von Klassen; • Variablen vom Typ Object können beliebige Objekt-Referenzen aufnehmen. • „Klassenmethoden“ wie „main()“, die sich auf die Klasse, d.h. den Prägestempel selbst beziehen. • Bei einer Wertzuweisung werden nur die Referenzen kopiert. => Es entstehen keine echten Kopien, sondern nur mehrfache Referenzen auf das selbe Objekt! „Normale“ Methoden haben Zugriff auf • die Parameter der Methode; • lokal (in der Methode) deklarierte Hilfsvariablen; • die Klassenvariablen der Klasse des Empfänger-Objekts; • die Exemplarvariablen des Empfänger-Objekts. • Um echte Kopien zu erstellen, redefiniert man die Methode public Object clone() Eine „Klassenmethode“ hat als Empfänger die Klasse, kein Objekt. aus Object geeignet und "castet" das Ergebnis passend: ¾ Zugriff auf Exemplarvariablen kann es daher nicht geben! (Zettel)z.clone() Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K2 - 7 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K2 - 8 Gezählte „Zettel“ Nummerierte „Zettel“ • Als Zähler wird eine mit 0 initialisierte Klassenvariable verwendet: • Der Zählerwert wird bei Initialisierung im Konstruktor aus der ererbten Klassenvariablen zaehler in eine Exemplarvariable nummer übernommen, die von da an unverändert bleibt, aber per „getter“ erreichbar ist: static int zaehler = 0 deren „getter“ dementsprechend eine Klassenmethode ist: public static int getNummer() public static int getZaehler() • Die Klasse „Nummeriert“ ist Unterklasse von „Gezaehlt“. • Die Klasse „Gezaehlt“ ist Unterklasse von „Zettel“. – „Gezaehlt“ hat zwei überladene Konstruktoren, wobei der mit einem Parameter sich per this(...) auf den anderen stützt. – „Nummeriert“ hat zwei überladene Konstruktoren, wobei der mit einem Parameter sich per this(...) auf den anderen stützt. – Der andere Konstruktor stützt sich seinerseits per super(...) auf den Konstruktor der Oberklasse „Zettel“. – Der andere Konstruktor stützt sich seinerseits per super(...) auf den Konstruktor der Oberklasse „Gezaehlt“. – Die Methoden clone() und toString() werden geeignet redefiniert. – Die Methoden clone() und toString() werden geeignet redefiniert. Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K2 - 9 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Nutzanwendung „Parkausweis“ Zettel # titel : String - inhalt : Object – „Parkausweis“ hat eine Exemplarvariable kennzeichen + getInhalt() : Object + setInhalt(Object) : void + toString() : String – „Parkausweis“ hat zwei überladene Konstruktoren, wobei der mit einem Parameter sich per this(...) auf den anderen stützt. Legende: – Der andere Konstruktor stützt sich seinerseits per super(...) auf den Konstruktor der Oberklasse „Nummeriert“. + public - private # protected – Die Methoden clone() und toString() werden geeignet redefiniert. – Eine Feinheit: Damit toString() in der gezeigten Weise auf die ererbte Exemplarvariable titel zugreifen kann, muß diese in „Zettel“ als protected , d.h. als in Unterklassen zugreifbar deklariert werden. Objektoiertierte Programmierung K2 - 10 Entstandene Klassenhierachie • Die Klasse „Parkausweis“ ist Unterklasse von „Nummeriert“. Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung Konstruktoren sind hier nicht explizit dargestellt! K2 - 11 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Seite 2 Gezaehlt - zaehler : int + getZaehler(): int + clone() : Object + toString() : String Nummeriert - nummer : int + getNummer(): int + clone() : Object + toString() : String Parkausweis - kennzeichen: String + clone() : Object + toString() : String Objektoiertierte Programmierung K2 - 12 Delegation in UML 2.3 Kooperation über Interfaces - titel : String # info : InfoInterface • Eintragungen wieder rückgängig machen; Die Aufgabe wird „auf mehrere Schultern“ verteilt. „enthält“-Beziehung, hier als Komposition sonst meist Aggregation • Dazu Trennung von Zettel und seiner Info. • Alles, was den Inhalt betrifft, delegiert Zettel an Info: Ein Zettel, der aufgefordert wird, etwas an seinem Inhalt zu tun, leitet die Aufgabe an seinen Partner Info weiter. Delegation u.a. Zettel.getInhalt() => Zettel.info.getInhalt() • Wichtig ist nicht, wer der Partner ist, sondern was er kann. • Das beschreibt das Interface InfoInterface. Partner „info“ leistet die Arbeit • Zettelpartner implementieren dieses Interface. Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K2 - 13 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Info-Anpassungen (Implementierung) «interface» RueckInterface + getInhalt() : Object + setInhalt(Object) : void + toString() : String SimpleRueckInfo MultiRueckInfo - aktInhalt : Object - voriger : Object - aktInhalt : Object - voriger : MultiRueckInfo + getInhalt() : Object + setInhalt(Object) : void + toString() : String + undo() : void + getInhalt() : Object + setInhalt(Object) : void + toString() : String + undo() : void EinfacheInfo - inhalt : Object + getInhalt() : Object + setInhalt(Object) : void + toString() : String Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Zettel - titel : String # info : InfoInterface „implementiert“Beziehung von Klasse zu Interface + undo() : void Objektoiertierte Programmierung + getInhalt() : Object + setInhalt(Object) : void + toString() : String K2 - 15 <attribute> : <werte> Exemplar / Instanz von Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) MultiRueckZettel + toString() : String + undo() : void persönl. Termin Objektoiertierte Programmierung Teamveranstaltung Hausveranstaltung Teambesprechung i.d.R. Klasse oder Interface K2 - 16 Reise Vortrag • In Entwurfsmodellen sollten Mehrfachvererbung beseitigt werden. Techniken dazu sind: – Ersatz von Vererbung durch Komposition – Definition von Schnittstellen <abstrakte Methoden> Objektoiertierte Programmierung SimpleRueckZettel + toString() : String + undo() : void Termin «interface» <Name> implementiert EinfacherZettel • In Analysemodellen treten oft unabhängige Dimensionen der Spezialisierung auf (Mehrfachvererbung). <zugriff> : + public - private # protected <Klasse> : konkret oder abstrakt <attribute> : <zugriff> <name> : <typ> <methoden> : <zugriff> <name> (<parameter>) : <typ> konkret oder abstrakt Unterklasse von „Vererbungs“Beziehung Mehrfachvererbung enthält <Klasse> <attribute> <methoden> K2 - 14 + toString() : String Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Zusammenfassung: UML-Elemente <objektName> : <Klasse> Objektoiertierte Programmierung Zettel-Anpassungen (Reimplementierung) „Vererbungs“-Beziehung zwischen Interfaces «interface» InfoInterface + getInhalt() : Object + setInhalt(Object) : void + toString() : String + getInhalt() : Object + setInhalt(Object) : void + toString() : String • zunächst einen Schritt („Undo/Redo“), später beliebig viele Schritte. <Klasse> <attribute> <methoden> «interface» InfoInterface Zettel Neue Aufgabe: K2 - 17 Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Seite 3 Objektoiertierte Programmierung K2 - 18 Ersatz von Vererbung durch Schnittstellen Ersatz von Vererbung durch Komposition • Guter Software-Entwurf sichert Homogenität. – Gleichartige Funktionalität soll in gleicher Weise aufrufbar sein. – Schnittstelle (interface) ist ein Sprachkonstrukt von UML und Java. Termin Termin 1 TeamRolle persönl. Termin Teamveranstaltung 1 OrtRolle Hausveranstaltung “implementiert” Teambesprechung einladen() absagen() Reise “Lollipop”-Notation: Teambesprechung nun wie realisiert? Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Objektoiertierte Programmierung K2 - 19 Abstrakte Klasse Schnittstelle („Interface“) Enthält Attribute und Operationen Enthält nur Operationen (und ggf. Konstante) Kann Default-Verhalten festlegen Default-Verhalten kann in Unterklassen überdefiniert werden Kann kein Default-Verhalten festlegen => Redefinition unmöglich Java: Unterklasse kann nur von einer Klasse erben Java: Eine Klasse kann mehrere Schnittstellen implementieren Schnittstelle ist eine „spezielle Sicht auf eine Klasse“ Objektoiertierte Programmierung Vortrag einladen() absagen() Teambesprechung Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) Schnittstellen und abstrakte Klassen Lothar Schmitz UniBwM (teils nach Prof. Hußmann TUD) <<interface>> Hausveranstaltung einladen() absagen() K2 - 21 Seite 4 Hausveranstaltung Objektoiertierte Programmierung K2 - 20