Kapitel 1 - Widerholungsfragen 1. Erklären Sie folgende Begriffe: • Objekt Ein Objekt ist eine logische Einheit, bestehend aus zusammengehörigen Variablen und Routinen. • Klasse Eine Klasse beschreibt die Struktur der ihr zugehörigen Objekte im Detail. Dazu gehören Eigenschaften, Methoden, Konstsruktoren, Destruktoren, etc. • Vererbung Vererbung ermöglicht es, neue Klassen (subclasses) von bereits existierenden Klassen (superclasses) abzuleiten. Änderungen können mittels Erweitern oder mittels Überschreiben vorgenommen werden. • Identität Objekte sind durch ihre Identität eindeutig gekennzeichnet und daher auch über diese ansprechbar. Vereinfacht kann man sich die Identität als die Adresse des Objekts im Speicher vorstellen. Das ist aber nur bedingt richtig, da sich die Speicheradresse eines Objekts ändern kann, die Identität aber erhalten bleibt. • Zustand Der Zustand eines Objekts setzt sich aus den Werten der Variablen im Objekt zusammen. Dieser ist zur Laufzeit abänderbar. • Verhalten Das Verhalten eines Objekts beschreibt, wie sich das Objekt beim Empfang einer Nachricht verhält, also was das Objekt beim Aufruf einer Methode macht. • Schnittstelle Sie beschreibt das öffentlich sichtbare Verhalten und entspricht dem Typen eines Objekts. Die Bezeichnungen white box, grey box, black box beschreiben den Grad an öffentlichen Methoden. • Instanz einer Klasse, einer Schnittstelle und eines Typs Die Instanzen einer Klasse sind jene Objekte, die durch Konstruktoren der Klasse erzeugt wurden. Genauer gesagt, sind die Objekte Instanzen der durch die Klasse beschriebenen Schnittstellen bzw. Typen. Die Klasse selbst ist die spezifischste aller Schnittstellen zu der das Objekt gehört, da sie das Verhalten am genauesten beschreibt. • Deklarierter Typ Der deklarierte Typ ist jener Typ, mit dem die Variable deklariert wurde. Er kann klarerweise nur bei expliziter Typdeklaration existieren. • Statischer Typ Der statische Typ wird vom Compiler statisch ermittelt und kann spezifischer als der deklarierte Typ sein. Statische Typen zum Beispiel für Programmoptimierung verwendet. Dabei hängt es vom der Qualität des Compilers ab, wie spezifisch der statische Typ ist. • Dynamischer Typ Das ist der spezifischste Typ den der in der Variable gespeicherte Wert tatsächlich hat. Er ist in der Regel spezifischer als der deklarierte Typ und wird zum Beispiel zur dynamischen Typüberprüfung während der Laufzeit verwendet. • Nachricht Objekte können während ihrer Lebenszeit Nachrichten austauschen. Dies ist als das Aufrufen von Methoden und Übersenden von Rückgabewerten zu verstehen. • Methode Eine Methode ist eine Routine eines Objekts. Das Verhalten eines Objekts beim Aufruf einer Methode ist von der Art und dem Inhalt der formalen Parameter der Methode abhängig. • Konstruktor Objekte einer Klasse werden durch einen Konstruktor erzeugt. Er ist eine spezielle Methode der Klasse. • Faktorisierung Unter Faktorisierung versteht man das Zusammenfassen zusammengehöriger Eigenschaften und Aspekte des Programms zu Einheiten. Gute Faktorisierung wirkt sich positiv auf die Wartbarkeit eines Programms aus. • Refaktorisierung Unter Refaktorisierung versteht man die Anpassung der Struktur eines Programms an neue oder unbedachte Gegebenheiten. Gute Faktorisierung kann den Aufwand von Refaktorisierung vermindern. • Verantwortlichkeiten • “was ich weiß“ – Beschreibung des Zustands der Instanzen • “was ich mache“ – Verhalten der Instanzen • “wen ich kenne“ – sichtbare Objekte, Klassen, etc. • Klassen-Zusammenhalt Der Klassen-Zusammenhalt ist hoch, wenn alle Variablen und Methoden der Klasse end zusammenarbeiten und der Name der Klasse gut beschrieben ist. • Objekt-Kopplung Die Objekt-Kopplung ist hoch, wenn die Anzahl der nach außen sichtbaren Methoden und Variablen hoch ist, im laufenden System Methodenaufrufe und Variablenzugriffe zwischen unterschiedlichen Objekten häufig auftreten und die Anzahl der Parameter dieser Methoden hoch ist. • Softwareentwurfsmuster Softwareentwurfsmuster geben Problemstellungen in der Softwareentwicklung einen Namen und bieten erprobte Lösungswege „best practices“ dafür an. Da sie meist nicht 1:1 anwendbar sind, wählt man jenen Weg, der am wenigsten andere Nachteile mit sich bringt. Konsequenzen sind oft die Aufblähung eines Systems, sowie eine schlechtere Übersichtlichkeit desselben. 2. Welche Arten von Polymorphismus unterscheidet man? Welche davon sind in der objektorientierten Programmierung wichtig? Warum? Man unterscheidet zwischen universellen- und Ad-hoc-Polymorphismus. Zum universellen Polymorphismus zählen Generizität und enthaltender Polymorphismus, zum Ad-hocPolymorphismus zählen das Überladen von Methoden und Typumwandlungen. Nur der universelle Polymorphismus ist für die objektorientierte Programmierung wichtig, da nur hier eine gleichförmige Struktur der untereinander in Beziehung stehenden Typen besteht. Weder das Überladen von Methoden, noch die Typumwandlung sind spezifisch für die objektorientierte Programmierung. 3. Wann sind zwei Objekte identisch, und wann sind zwei identische Objekte gleich? Es gibt keine zwei identen Objekte. Zwei unterschiedlich benannte Referenzen können höchstens auf ein und dasselbe Objekt verweisen. Zwei Objekte sind genau dann gleich, wenn sie denselben Zustand und dasselbe Verhalten aufweisen (Kopien voneinander sind). 4. Sind Datenabstraktion, Datenkapselung und data hiding einander entsprechende Begriffe? Wenn Nein, worin unterscheiden sie sich? Nein, sind sie nicht! Unter Datenkapselung versteht man das Zusammenfassen zusammengehöriger Aspekte eines Programms zu einer Einheit (Kapsel). Unter data hiding versteht man das verstecken von Daten und Implementierungen. Datenabstraktion ist ein Sammelbegriff für Datenkapselung und data hiding. 5. Was besagt das Ersetzbarkeitsprinzip? Dies besagt, dass ein Typ U genau dann ein Untertyp vom Typen T ist, wenn eine Instanz vom Typ U überall dort eingesetzt werden kann, wo eine Instanz vom Typen T erwartet wird. 6. Nennen Sie die Schritte im Softwareentwicklungsprozess entsprechend dem Wasserfallmodell und zyklischen Modellen. Das Wasserfallmodellen besteht aus den Schritten: Analyse, Entwurf, Implementierung sowie Verifikation und Validierung. Zyklische Modelle wenden das Wasserfallmodell in Form schrittweiser Verfeinerung auf das Gesamtprojekt an, indem Teilaspekte immer weiter ausgebaut und ständig verifiziert und validiert werden. 7. Warum ist eine gute Wartbarkeit so wichtig? Änderungen der Software können rascher durchgeführt werden, langfristige Kosten können dadurch gesenkt werden. 8. Wie lauten die wichtigsten Faustregeln im Zusammenhang mit KlassenZusammenhalt und Objekt-Kopplung? Welche Vorteile erwartet man sich davon, dass diese Faustregeln erfüllt sind? Der Klassen-Zusammenhalt soll hoch sein. Hoher Klassen-Zusammenhalt deutet auf eine gute Faktorisierung hin. Bei guter Faktorisierung muss die Struktur einer Software nur minimal an Änderungen angepasst werden. Die Objekt-Kopplung soll schwach sein. Schwache Objekt-Kopplung deutet auf eine gute Kapselung hin. Bei Änderungen werden vermutlich weniger Objekte beeinflusst als bei starker Objekt-Kopplung. 9. Welche Arten von Software kann man wieder verwenden, und welche Rolle spielt jede davon in der Softwareentwicklung? Programme, Daten, Erfahrungen („best practices“) und Code. Unter Code unterscheidet man weiters zwischen globalen- und fachspezifischen Bibliotheken, projektinterner- und programminterner Wiederverwendung. 10.Welche Rolle spielen Refaktorisierungen in der Wiederverwendung? Besonders bei weniger erfahrenen Programmierern kann der erhöhte Zeit- und Kostenaufwand bei der Erstellung wiederverwendbarer Software zum Scheitern des Projekts führen. Im Zweifelsfall sollte erst nach Fertigstellung des Projekts und nach Bedarf eine Refaktorisierung für Wiederverwendung erwogen werden. 11.Nennen Sie die wichtigsten Paradigmen der Programmierung und ihre essentiellen Eigenschaften. Zur Imperativen Programmierung gehören die Prozedurale- und die Objektorientierte Programmierung, zur Deklarativen Programmierung gehören die Funktionale- und die Logikorientierte Programmierung. 12.Wofür ist die objektorientierte Programmierung gut geeignet, und wofür ist sie nicht gut geeignet? Objektorientierte Programmierung eignet sich zur Entwicklung von Systemen, deren Gesamtkomplexität jene der einzelnen Algorithmen deutlich übersteigt. Sonst sind andere Paradigmen besser geeignet. Kapitel 2 – Wiederholungsfragen 13.In welcher Form kann man durch das Ersetzbarkeitsprinzip Wiederverwendung erzielen? Durch das Einhalten des Ersetzbarkeitsprinzips können Fehler in der Klassenhierarchie vermieden und Schnittstellen stabil gehalten werden. Dadurch ergeben sich ein paar Möglichkeiten zur Wiederverwertung, s. Beispiel Treiberversionen. 14.Unter welchen Bedingungen, die von einem Compiler überprüfbar sind, ist ein Typ im Allgemeinen Untertyp eines anderen Typs? Welche zusätzlichen Bedingungen müssen in Java gelten? Typen von Konstanten und Ergebnistypen müssen kovariant, Typen formaler Parameter kontravariant und Variablentypen invariant sein. In Java muss zudem zwischen den beiden Klassen eine Vererbungsbeziehung bestehen. 15.Sind die in Punkt 14 angeschnittenen Bedingungen hinreichend, damit das Ersetzbarkeitsprinzip erfüllt ist? Wenn nicht, was muss noch beachtet werden? Damit das Ersetzbarkeitsprinzip vollständig erfüllt sein kann, muss der Programmierer den Vertrag zwischen Client- und Serverklassen implementieren. 16.Welche Rolle spielt dynamisches Binden für die Ersetzbarkeit und Wartbarkeit? Durch den Einsatz dynamischen Bindens können Änderungen rascher Angepasst werden, die Lokalität bleibt gewährleistet, was wiederum und Wartbarkeit verbessert. 17.Welche Arten von Zusicherungen werden unterschieden, und wer ist für deren Einhaltung verantwortlich? Vorbedingungen (dafür ist der Client verantwortlich), Nachbedingungen (dafür ist der Server verantwortlich) und Invarianten (für die ebenfalls der Server vor und nach Aufruf einer seiner Methoden zuständig ist). 18.Wie müssen sich Zusicherungen in Unter- und Obertypen zueinander verhalten, damit das Ersetzbarkeitsprinzip erfüllt ist? Vorbedingungen im Untertypen dürfen nur schwächer werden (mittels ODER), Nachbedingungen und Invarianten dürfen im Untertypen nur stärker sein (mittels UND). 19.Warum sollen Schnittstellen und Typen stabil bleiben? Wo ist Stabilität besonders wichtig? Nachträgliche Änderungen wurden sich über die gesamte zu Grunde liegende Vererbungshierarchie ausbreiten. Während Blätter zwecks Stabilitätsgewinnung noch leicht refaktorisiert werden können, müssen Elemente zur Wurzel hin stabil bleiben. 20.Was ist im Zusammenhang mit allgemein zugänglichen (public) Variablen und Invarianten zu beachten? (Öffentliche) Variablen von außen zu verändern sollte man auf jeden Fall unterlassen. Sind dabei Invarianten betroffen, könnte dies zu einer Verletzung des Vertrags führen. 21.Wie genau sollen Zusicherungen spezifiziert sein? Zusicherungen sollten möglichst allgemein gehalten werden. Je genauer die Zusicherungen formuliert sind, desto eher ist die Stabilität gefährdet. 22.Wozu dienen abstrakte Klassen und abstrakte Methoden? Wo und wie soll man abstrakte Klassen einsetzen? Abstrakte Klassen können zwar nicht instanziert werden, eignen sich aber zum Definieren von Typen. Abstrakte Methoden müssen in den Untertypen implementiert werden. Abstrakte Klassen ohne Implementierungen eigenen sich gut als Obertypen, da sie eher stabil sind und man immer von stabilen Typen ableiten soll. 23.Ist Vererbung dasselbe wie das Ersetzbarkeitsprinzip? Wenn Nein, wo liegen die Unterschiede? Für eine reine Vererbungsbeziehung ist das Ersetzbarkeitsprinzip irrelevant. Letzteres ist eine Einschränkung der Freiheiten des Programmierers, Vererbungstechniken willkürlich zu Gunsten von Untertypbeziehungen einzusetzen. 24.Worauf kommt es zur Erzielung von Codewiederverwertung eher an – Auf Vererbung oder Ersetzbarkeit – Warum? Auf Ersetzbarkeit! Vererbungsbeziehungen bieten auf den ersten Blick die bessere Codewiederverwertung, allerdings verzichtet man auf Untertypbeziehungen, die Codewiederverwertung im noch größeren Umfang bewirken können und ein wichtiges Instrument der objektorientierten Programmierung sind. 25.Was bedeuten folgende Begriffe in Java? • • • Instanzvariable Instanzvariablen sind jene Variablen die zu den Instanzen der Klasse gehören. Jede Instanz verfügt über eine eigene Kopie dieser Variable. Klassenvariable Klassenvariablen gehören zur Klasse selbst. Schreibzugriffe auf eine Klassenvariable wirken sich auf alle Instanzen aus. statische Methode Statische Methoden gehören ebenfalls zur Klasse selbst und werden über den Namen der Klasse aufgerufen. this ist innerhalb von statischen Methoden nicht verfügbar. • static initializer Der static initializer ist ein Block für Initialisierungen von statischen Variablen, ähnlich dem Konstruktor für Instanzvariablen. • Geschachtelte und innere Klasse Es gibt zwei Arten geschachtelter Klassen: statische geschachtelte Klassen und innere Klassen. Statische geschachtelte Klassen dürfen nur auf statische Felder der umschließenden Klasse zugreifen. Innere Klassen gehören zur Instanz der umschließenden Klasse und dürfen weder statische Methoden noch statisch geschachtelte Methoden enthalten. Abgesehen davon entsprechen geschachtelte Klassen den nicht geschachtelten Klassen: sie können abstract sein und von anderen Klassen erben. • final Klasse und final Methode Von final Klassen kann nicht geerbt werden, final Methoden können nicht im Untertypen überschrieben werden. • Paket Ein Paket dient der Schaffung einer Struktur für Klassen. Zusammengehörige Klassen sollen sich in einem Paket befinden. 26.Wo gibt es in Java Mehrfachvererbung, wo Einfachvererbung? Mehrfachvererbung wird in Java mittels implementierter Interfaces realisiert, Einfachvererbung mittels Erweiterung von Klassen. 27.Welche Arten von import-Deklarationen kann man in Java unterscheiden? Man kann einzelne Klassen oder alle Klassen eines Pakets per Wildcard (*) importieren. 28.Welche Möglichkeiten zur Spezifikation der Sichtbarkeit gibt es in Java, und wann soll man welche Möglichkeit wählen? Public, private, protected und default (package access). Methoden, Konstanten und Variablen die bei der Verwendung der Klasse oder ihrer Instanzen benötigt werden, müssen public sein. Methoden, Konstanten und Variablen die nur innerhalb der Klasse verwendet werden, sollen private sein. Methoden und Variablen, die für die Verwendung einer Klasse oder ihrer Instanzen nicht benötigt werden, aber für spätere Erweiterungen benötigt werden könnten, sollen protected sein. 29.Was sind Interfaces in Java, und wodurch unterscheiden sie sich von abstrakten Klassen? Wann soll man Interfaces verwenden? Wann sind abstrakte Klassen besser geeignet? Interfaces sind Definitionen von Schnittstellen. Es dürfen keine Variablen, nur Konstanten definiert werden, alle Methoden sind automatisch public. Die Schlüsselwörter static, final, private und protected dürfen in Methodendeklarationen nicht vorkommen. Interfaces sind auf Grund von Mehrfachvererbung mittels implements flexibler einsetzbar als Klassen und sind wegen der höheren Stabilität (fehlende Implementierungen) besser geeignet als Klassen. Kapitel 3 – Wiederholungsfragen 30.Was ist Generizität? Wozu verwendet man Generizität? Generizität ist neben enthaltendem Polymorphismus eine weitere Form des universellen Polymorphismus. Generizität wird zur Erstellung generischer Klassen mit Typparametern eingesetzt. Der Vorteil liegt in der statischen Typsicherheit sowie in der Codeersparnis bei sich nur durch jeweils einen Typen voneinander unterscheidenden Klassen. 31.Was ist gebundene Generizität? Was kann man mit Schranken auf Typparametern machen, was ohne Schranken nicht geht? Bei gebundener Generizität wird auf einem Typparameter eine Schranke definiert. Durch diese Schranke ist der zu verwendende Typ näher spezifizierbar (im Gegensatz zu einfacher Generizität). Wird keine Schranke definiert, so wird implizit Object als Schranke angenommen. 32.In welchen Fällen soll man Generizität einsetzen, in welchen nicht? In erster Linie sollte man Ersetzbarkeit anwenden, in zweiter Linie Generizität. 33.Was bedeutet statische Typsicherheit? Der Compiler garantiert bereits, dass tatsächlich nur erwartete Typen verwendet werden. Dadurch werden Typkonvertierungsfehler zur Laufzeit ausgeschlossen. 34.Welche Arten von Generizität hinsichtlich ihrer Übersetzung und ihrem Umgang mit Schranken kann man unterscheiden? Welche davon wird in generischem Java verwendet, und wie flexibel ist diese Lösung? 35.Was sind (gebundene) Wildcards als Typen in Java? Wozu kann man sie verwenden? Gebundene Wildcards definieren eine Schranke auf einem formalen Parameter einer Methode bei der Verwendung eines generischen Typen. z.B.: public meth(List<? extends Polygon> p) { … } 36.Wie kann man Generizität simulieren? Worauf verzichtet man, wenn man Generizität nur simuliert? 37.Was wird bei der heterogenen bzw. homogenen Übersetzung von Generizität genau gemacht? 38.Welche Möglichkeiten für dynamische Typabfragen gibt es in Java, und wie funktionieren sie genau? 39.Was wird bei einer Typumwandlung in Java umgewandelt – der deklarierte, dynamische oder statische Typ? Warum? 40.Welche gefahren bestehen bei Typumwandlungen? 41.Wie kann man dynamische Typabfragen und Typumwandlungen vermeiden? In welchen Fällen kann das schwierig sein? 42.Welche Arten von Typumwandlungen sind sicher? Warum? 43.Was sind kovariante Probleme und binäre Methoden? Wie kann man mit ihnen umgehen oder sie vermeiden? 44.Wie unterscheidet sich Überschreiben von Überladen, und was sind Multimethoden? 45.Wie kann man Multimethoden simulieren? Welche Probleme können dabei auftreten? 46.Was ist das Visitor-Entwurfsmuster? 47.Wodurch ist das Überladen problematisch, und in welchen Fällen ergeben sich kaum Probleme? 48.Wie werden Ausnahmebehandlungen in Java unterstützt? 49.Wie sind Ausnahmen in Untertypbeziehungen zu berücksichtigen? 50.Wozu kann man Ausnahmen verwenden? Wozu soll man sie verwenden, wozu nicht?