8. Objektorientierte Programmierung
 
Fenster schliessen
Allgemeine Einführung in die objektorientierte Programmierung


Bisherige Programmierungsansätze

Die objektorientierte Programmierung wurde entwickelt, weil die Softwareentwickler bei den früheren Ansätzen der Programmentwicklung (Funktions- und Datenfluß-Orientierung) auf massive Hindernisse und Grenzen stießen. Um die Bedeutung der objektorientierten Programmierung richtig beurteilen zu können, wird erläutert, um welche Grenzen es sich handelt.

Ada, Basic, C und Pascal sind Beispiele für prozedurale Sprachen; einzelne Anweisungen dieser Sprache befehlen dem Computer, etwas zu tun. Ein großes Programm besteht aus vielen Anweisungen. Weil eine große Anzahl von Anweisungen, die mit Schleifen und Sprüngen durchsetzt sind, für den Programmierer schwer zu handhaben ist, wurde eine Aufteilung in Unterprogramme notwendig.

Ein Programm wird in Unterprogramme unterteilt, wobei jedes Unterprogramm einen eindeutig festgelegten Zweck und eine definierte Schnittstelle hat. Konzeptionell zusammengehörige Unterprogramme können als eigenständige Einheit zu einem Modul zusammengefaßt werden. Die meisten Programmiersprachen unterstützen dieses Modulkonzept, das auch als funktionsorientierte Programmierung bezeichnet wird


Schwachpunkte der funktionsorientierten Programmierung

Wenn Programme immer größer und komplexer werden, zeigen sich die Schwachpunkte der funktionsorientierten Programmierung.

In einer Prozeduralsprache liegt der Schwerpunkt auf dem Handeln, den Daten fällt eher eine Nebenrolle zu. Viele Unterprogramme greifen auf dieselben Daten zu, so daß es schwer wird, die Zugriffe (wer, wann, was, warum) zu verfolgen oder Teilkomponenten der Daten zu verändern. Wenn hier der Zugriff auf die Daten in der Form beschränkt wird, daß man sie nur über ausgewählte Unterprogramme ansprechen kann, erhöht man die Datensicherheit erheblich.


Ein erster Ansatz dazu ist der Begriff des abstrakten Datentyps (ADT - Abstrakter Datentyp), der es ermöglicht, Daten und die Unterprogramme, die diese Daten manipulieren, in einer einzigen Einheit zusammenzufassen.

Ein ADT besteht aus einem Datentyp (einfacher Typ, Verbund, Reihungstyp o. ä.) und einer Menge von Unterprogrammen, die Variable dieses Datentyps manipulieren. Das Hauptproblem eines ADTs liegt in der Tatsache begründet, daß die Manipulation nicht nur durch die dafür vorgesehenen Unterprogramme durchgeführt werden kann, sondern auch direkt durch Ändern der Werte der Variablen.



Einige Programmiersprachen bieten hier Strukturierungsmittel, die dafür sorgen, daß ein Nutzer des ADT nur die Unterprogramme zur Manipulation, nicht aber den Datentyp sieht.

Trotzdem ist das Konzept des abstrakten Datentyps nicht ausreichend, die Komplexität moderner Softwareanforderungen umzusetzen.


Der objektorientierte Ansatz

Die objektorientierte Programmierung (OOP) basiert auf dem Konzept der abstrakten Datentypen und ergänzt es um eine Reihe neuer Eigenschaften (Kapselung, Vererbung, Polymorphie, Abstraktion). Sie bietet neue, leistungsfähige Wege, um die wachsende Komplexität von Programmen in den Griff zu bekommen.

Das Ziel von OOP sind übersichtlichere und zuverlässigere und damit auch leichter wartbare Programme. OO-Programme bauen sich um Objekte herum auf, die sowohl Daten als auch die Funktionen zu ihrer Manipulation enthalten. Diese Objekte kommunizieren durch Aufrufe der Komponentenfunktionen miteinander.

Diese neuen Einheiten, die aus Daten und zugehörigen Funktionen gebildet werden, werden als Klassen bezeichnet, welche untereinander wiederum Beziehungen (u. a. Vererbung) haben können.


Objekte und Klassen

Die Definition einer Klasse erzeugt ein Schema, welches die Daten und die Komponentenfunktionen festlegt. Instanzen dieser Klasse [Instanz (OOP)] werden als Objekte bezeichnet. Jedes Objekt besitzt die gleichen Komponentenfunktionen wie alle anderen Objekte derselben Klasse.

Ein Objekt besitzt lokale Daten. Die Manipulation dieser internen Daten ist nur über die Komponentenfunktionen der zugehörigen Klasse möglich.


Eine Klasse besteht aus:

  • Komponentenfunktionen
  • internen "Unterprogrammen"
  • lokalen Daten
  • evtl. globalen Daten für alle Objekte einer Klasse gemeinsam




Vererbung

Mehrere Klassen bilden eine Klassenhierarchie, wenn man Klassen von vorhandenen Klassen ableitet.

Die Klasse, die selbst nicht von anderen Klassen abgeleitet wurde, wird zu einer Basisklasse, die anderen Klassen werden zu abgeleiteten Klassen. Jede abgeleitete Klasse besitzt also eigene Eigenschaften und zusätzlich die Eigenschaften aller Klassen, von denen sie abgeleitet wurde.





Die Bildung von Klassen hat positive Auswirkungen auf die Wiederverwendbarkeit von Software. Ein Programmierer kann eine (funktionsfähige, ausgetestete) Klasse nehmen und ihr zusätzliche Eigenschaften verleihen, indem er von einer vorhandenen Klasse eine neue Klasse ableitet und mit zusätzlichen Eigenschaften versieht. Die Erweiterung findet statt, ohne daß die bisherige Klasse geändert oder auch nur rekompiliert werden muß.


Polymorphismus

Unterprogrammnamen können mehrfach auftreten und sind damit überladen und mehrdeutig. Der Übersetzer löst diese Mehrdeutigkeit auf, indem er beim Aufruf eines solchen Unterprogramms anhand der Parameterliste das passende Unterprogramm bestimmt (statische Bindung). Voraussetzung dafür ist immer, daß die Unterprogramme eine unterschiedliche Parameterliste besitzen.

Ein einfaches Beispiel zur Auflösung der Mehrdeutigkeit stellt die Addition dar.
Der Übersetzer muß zur Addition von Integer-Zahlen andere Maschinen-instruktionen erstellen als zur Addition von Gleitpunktzahlen. Die Unterscheidung trifft er anhand der Datentypen der zu addierenden Variablen.
Die Auflösung solcher Mehrdeutigkeiten zur Übersetzungszeit (statische Bindung) ist jedoch auch in Übersetzern vieler Programmiersprachen ohne OOP-Erweiterungen vorhanden.

Wenn die gleichnamigen Unterprogramme in einer Klassenhierarchie auftreten und keine unterschiedliche Parameterliste besitzen, dann kann zur Übersetzungszeit noch keine Klassen- und Unterprogrammzuordnung getroffen werden. Diese Zuordnung muß dann zur Laufzeit vorgenommen werden, indem zusätzliche Informationen ausgewertet werden, die erst zu diesem Zeitpunkt zur Verfügung stehen (dynamische Bindung).

Diese Vorgehensweise wird als Polymorphismus bezeichnet und ist ein Charakteristikum von objektorientierten Programmiersprachen.
erliste besitzen, dann kann zur Übersetzungszeit noch keine Klassen- und Funktionszuordnung getroffen werden. Diese Zuordnung muß dann zur Laufzeit vorgenommen werden, indem zusätzliche Informationen ausgewertet werden, die erst zu diesem Zeitpunkt zur Verfügung stehen. Diese Vorgehensweise ist ein Charakteristikum von objektorientierten Programmiersprachen.


Dynamische Bindung

Die Unterprogrammzuordnung zur Laufzeit wird auch als "dynamische Bindung" bezeichnet.

Der Übersetzer muß speziellen Code generieren, der zur Laufzeit:

a) die Klasse anhand der Datentypen der aktuellen Objekte bestimmt;
b) in einer Tabelle das entsprechende Unterprogramm ermittelt;
c) dieses Unterprogramm aufruft.

Bei statischer Bindung wird zur Laufzeit nur c) ausgeführt, weil der Übersetzer die Teile a) und b) schon zur Übersetzungszeit auflösen konnte.

Der Vorteil der dynamischen Bindung wird jedoch mit etwas größerer Laufzeit erkauft, weil das passende Unterprogramm erst in einer Tabelle gesucht werden muß.

Die dynamische Bindung findet man nur in Übersetzern, die die objektorientierte Programmierung unterstützen.


Operatorüberladung


Die Operatorüberladung ist ein weiteres wesentliches Merkmal der objektorientierten Programmierung.

Sie ermöglicht es, eigene Operationen zu deklarieren und damit schwer verständliche Anweisungen in besser lesbare und leichter verständliche Form zu bringen:


Z := addiere ( X, Y );

in

Z := X + Y;


Die Operatorüberladung ermöglicht, die Sprache auf die eigenen Bedürfnisse abzustimmen.

Als Operatoren zur Überladung können die Standard-Operatoren der jeweiligen Sprache benutzt werden. Oft sind jedoch einige Operatoren von der Bearbeitung ausgeschlossen.

Auch Operatoren können wie Unterprogramme (Unterprogrammüberladung) mehrfach überladen werden. Der passende Operator wird wie bei Unterprogrammaufrufen anhand der Parameter ausgewählt.

Fenster schliessen


 
zurück
  Ada Tour - Dokumentation  
© 2003 Förderverein Ada Deutschland e.V.