Objektorientierte Programmierung III
OOP Kapselung: Gruppierung von Daten und Funktionen als Objekte. Definieren eine Schnittstelle zu diesen Objekten. Vererbung: Erlaubt Code zwischen verwandten Typen wiederverwendet sein. Polymorphismus: Ein Objekt kann einer von mehreren Typen sein. Abhängig von seinem Typ wird seinem Verhalten zur Laufzeit bestimmt.
Vererbung/Inheritance I Ermöglicht ein Definieren einer neuen Klasse (Unterklasse) durch die Definition einer anderen Klasse (Oberklasse). Vererbung macht Wiederverwendbarkeit des Codes möglich. Wiederverwendbarkeit ist die Verwendung eines vorhandenen Codes (Klassen). Der Aufwand der Entwicklung eines Programms wird reduziert. Software ist robuster.
Vererbung II Durch Vererbung können neue Klassen abgeleitet werden. Die vorhandene Klasse wird nicht geändert. Die neue Klasse kann alle Funktionen der alten Klasse und fügt neue Funktionen hinzu. Vererbung kann verwendet werden, wenn es eine is a/kind of -Beziehung zwischen den Objekten gibt.
Beispiel
Einfache Vererbung I mindestens zwei Klassen sind erforderlich: eine Basisklasse und eine abgeleitete Klasse. Wenn B und D zwei Klassen sind, D erbt von B oder D ist abgeleitet von B oder D ist eine Spezialisierung von B das heißt: D enthält alle Variablen und Methoden der Klasse B; D kann Methoden der Klasse B umschreiben; D kann neue Attribute hinzufügen.
Einfache Vererbung II Wenn Klasse D von Klasse B erbt, dann: Ein Objekt der Klasse D enthält alle Attribute der Klasse B; Die Methoden der Klasse B können durch Objekte der Klasse D aufgerufen werden (außer wenn sie versteckt sind).
Einfache Vererbung III
Einfache Vererbung IV DEMO
Einfache Vererbung V Fachbegriffe B = Oberklasse, Basisklasse, Elternklasse. D = Unterklasse, abgeleitete Klasse, Subklasse, Kindklasse geerbte Members (Methoden, Attribute) = ein Element definiert in B und unverändert in D redefined member (overridden/überschreiben) = definiert in B und D. added member (new) = nur in D definiert
Zugriffsmodifikatoren I public: public Members können von überall zugegriffen werden. private: private Members können von innerhalb der Klasse oder von Freunden Funktionen/Klassen zugegriffen werden protected: protected Members können von innerhalb der abgeleiteten Klassen zugegriffen werden protected ist wie privat. Abgeleiteten Klassen haben Zugriff auf protected Members (aber nicht auf private Members) Friend Funktionen/Klassen können auf protected Mitglieder zugreifen
Zugriffsmodifikatoren II
Zugriffsmodifikatoren III public Vererbung: Die Zugangsberechtigungen der Mitglieder der Basisklasse sind nicht geändert. protected Vererbung: Geerbte public oder protected Members der Basisklasse werden protected Members in der abgeleiteten Klasse gewesen. private Vererbung: Geerbte public oder protected Members der Basisklasse werden private Members in der abgeleiteten Klasse gewesen.
Zugriffsmodifikatoren IV
Spezielle Methoden und Vererbung Einige Funktionen müssen verschiedene Dinge in der Basisklasse und in der abgeleiteten Klasse machen. Diese speziellen Funktionen können nicht vererbt werden. Konstruktoren: der konstruktor der abgeleiteten Klasse muss andere Daten erstellen. Assignment Operator: In der abgeleiteten Klasse dieser Operator muss den abgeleiteten Daten Werte zuweisen. Destruktoren
Konstruktors/Destruktors/Vererbung Konstruktoren und Destruktoren werden nicht geerbt. Konstruktoren in der abgeleiteten Klasse müssen einen Konstruktor der Basisklasse aufrufen. Wenn kein Konstruktor explizit aufgerufen wird, der Default-Konstruktor der Basisklasse wird automatisch aufgerufen. kein Default-Konstruktor Compilerfehler. Ist das sein möglich?
Konstruktors/Destruktors/Vererbung Wenn ein Objekt einer abgeleiteten Klasse erstellt wird, wird der Konstruktor der Basisklasse zuerst aufgerufen (und dann der Konstruktor der abgeleiteten Klasse). Der Destruktor der Basisklasse wird automatisch von der Destruktor der abgeleiteten Klasse aufgerufen. Wenn ein Objekt einer abgeleiteten Klasse zerstört wird, wird der Destruktor der abgeleiteten Klasse zuerst aufgerufen (und dann der Destruktor der Basisklasse).
Konstruktors/Destruktors/Vererbung Erzeugen/Anlegen: 1. Reservieren von benötigten Ressourcen für Variablen der Basisklasse; 2. Reservieren von benötigten Ressourcen für Variablen der abgeleiteten Klasse; 3. Ein Konstruktor wird ausgesucht und aufgerufen, um die Variablen der Basisklasse zu initialisieren; 4. Ein Konstruktor wird ausgesucht und aufgerufen, um die Variablen der abgeleiteten Klasse zu initialisieren. Zerstörung: 1. Destruktoraufruf für die abgeleitete Klasse; 2. Destruktoraufruf für die Basisklasse.
Liskovsches Substitutionsprinzip Wenn S ein Subtyp von T ist, sollten Objekte vom Typ S verhalten, wie Objekte des Typs T verhalten sollen, wenn sie als Objekte des Typs T behandelt werden. Ein Objekt der abgeleiteten Klasse kann in jedem Kontext, in dem ein Objekt der Basisklasse erwartet wird, verwendet werden (Upcasting ist implizit). Barbara H. Liskov and Jeannette M. Wing, A Behavioral Notion of Subtyping, ACM Transactions on Programming Languages and Systems, 1994.
Zeiger und Vererbung ein Zeiger auf D kann auf Variablen vom Typ Zeiger auf B zugewiesen werden ein Zeiger auf ein Objekt vom Typ B kann die Adresse eines Objekts vom Typ D tragen Z. B.: Ein Zeiger auf ein Tier kann auf Objekte des Typs Tier, Hund und Pinguin zeigen (alle Hunde und Pinguine sind Tiere).
Überschreiben von Methoden Eine abgeleitete Klasse kann einige Methoden der Basisklasse überschreiben. Bei der Definition abgeleiteten Klassen muss man nur festlegen, was von der Basisklassen geändert hat (programming by difference). Vererbung erlaubt nur das Überschreiben von Methoden und das Hinzufügen neuen Methoden/Attribute. Man kann die vorhandene Funktionalität der Basisklasse nicht entfernen. Scope operator :: Überschreiben!= Überladen
UML UML - Unified Modelling Language Die Standardsprache in Industrie zum Spezifizieren, Visualisieren, Erstellen und Dokumentieren der Artefakte von Softwaresysteme. Die Standard-Notation für Softwarearchitektur. UML ist sprachunabhängig
Klassendiagramme Ein UML-Klassendiagramm spezifiziert die Entitäten in einem Programm und die Beziehungen zwischen ihnen. Es enthält und spezifiziert: Klassenname Attribute (Name, Typ) Methoden (Name, Parametertypen, Rückgabetyp) private Members: -; public Members: +; protected Members: #.
Assoziation I UML-Assoziationen beschreiben Beziehungen struktureller Abhängigkeit zwischen den Klassen. Ein Assoziation kann haben: Name; Kardinalität; Navigierbarkeit (uni / bidirektional). Assoziation (knows-a) - ist eine Beziehung zwischen zwei Klassen. Eine Klasse A enthält eine Referenz zu einer anderen Klasse B.
Assoziation II Komposition (has-a) - wenn Klasse B ist ein Teil von Klasse A, steuert die Klasse A die Lebensdauer von der Instanz der Klasse B. Diese Instanz wird zerstört, wenn die Instanz der Klasse A zerstört wird.
Assoziation III Abhängigkeit/Dependency (uses-a) - wenn Klasse A in einer Methode einen Referenz auf Klasse B verwendet (Parameter oder lokal Variable). Eine Änderung in der Klasse B kann A beeinflussen.
Assoziation IV Vererbung (is-a) - jede Instanz der abgeleiteten Klasse ist eine Instanz der Basisklasse.
Assoziation V Vererbung erlaubt die Definition den Hierarchien von verwandten Klassen.
Mehrfachvererbung I Im Gegensatz zu vielen objektorientierten Sprachen erlaubt C++ eine Klasse mehrere Basisklassen haben. Die Klasse erbt alle Members von der Basisklassen. Mehrfachvererbung kann problematisch sein: das gleiche Attribute/ die gleiche Methode könnte von anderen Klassen geerbt werden; wiederholte Basisklassen. Im Allgemeinen soll man Mehrfachvererbung vermeiden
Mehrfachvererbung II Probleme Unklarheit: mehrere Basisklassen enthalten eine Methode mit dem gleichen Name. Diamond-Problem: eine Methode der Klasse Animal ist in beiden Klassen überschrieben worden (Mammal und WingedAnimal). Welche der beiden Versionen sollte vererbt werden?