Home Computer Pascal Kurs Site Map counter

Jetzt lerne ich Pascal... Teil 7

Objektorientiertes Programmieren

Eine ordentliche Programmiersprache muss heute objektorientiert sein, und wer was auf sich hält redet gerne von Objekten, Vererbung und Polymorphismus. Damit kann man mordsmäßig Eindruck schinden. Doch was ist das eigentlich?

Ein Objekt

Wenn Sie ein Programm schreiben, so haben sie in der Regel Daten die sie bearbeiten und Routinen die dies tun. Es werden nicht die einzigen Daten sein, denn Sie haben oft auch Zwischenvariablen und Laufvariablen und Code, der nichts mit ihren Daten zu tun hat aber ihr Benutzerinterface bildet, aber immer werden Sie Daten und Code haben um diese zu verarbeiten.

In den siebziger Jahren kam aus dem berühmten Xerox Parc die Idee eine Programmiersprache zu entwickeln, die dies vereint. Es war Smalltalk, die erste objektorientierte Programmiersprache. Seitdem gibt es weitere Programmiersprachen die objektorientiert sind: C++, Java und natürlich als erste PC Programmiersprache Turbo Pascal und der Nachfolger Delphi.

Ein Objekt ist nichts anderes als Ein Verbund von Daten und Routinen um diese Daten zu bearbeiten. In der Objektorientierten Sprache nennt man die Routinen Methoden. Die Daten selber Felder. In Pascal wird dies in einer Konstruktion gelöst die einem Record sehr ähnlich ist:

type
Stringfeld object
Feld : Array [1..100] of string;
function getitem(const i : integer): string;
procedure setitem(const i : integer; const item : string);
end;

Dies führt eine Objektdefinition ein, die ein Stringfeld enthält sowie zwei Routinen um einen Eintrag in dieses Feld zu schreiben und zu lesen. Dies ist eine Typvereinbarung, und wie bei einem Record kann man nun Variablen davon anlegen:

var meinfeld: stringfeld;

Sie haben sicher bemerkt das die Routinen zwar definiert sind, aber es keinen Code dafür gibt. Das muss man nun nachholen. Üblicherweise definiert man Objekte im Interface Teil einer Unit und die Routinen dann im implementation Teil:

interface
type
Stringfeld object
Feld : Array [1..100] of string;
function getitem(const i : integer): string;
procedure setitem(const i : integer; const item : string);
end;

implementation

function
stringfeld.getitem(const i : integer): string;

begin
if
i in [1..100] then getitem:=feld[i] else .getitem:='';
end;

procedure stringfeld.setitem(const i : integer; const item : string);

begin
if
i in [1..100] then feld[i]:=item;
end;

Sie stellen fest, das die Routinen die Form objektname.routinenname(...) haben. Ein Objekt namens Stringfeld hat also Routinen die mit stringfeld. anfangen wie die Datenfelder eines Records. Das ist für den Anfänger etwas verwirrend. In Pascal hat es sich daher eingeführt vor den Objekttyp ein T zu setzen um zu verdeutlichen es ist ein Typ und die Routinen sind Methoden dieses Typs. Beachten Sie weiterhin das in den Methoden nicht stringfeld.getitem undstringfeld.feld steht: Damit das es eine Methode von Stringfeld ist, ist klar das hier angesprochene Methoden und Felder auch zu stringfeld gehören.

In der Sprechweise der OOP (Objektorientierte Programmierung) unterscheidet man nun zwei Dinge: Das was sie hier gesehen haben ist eine Klasse. Eine Klasse ist ein Bauplan für ein Objekt oder sagen wir es in Pascal: Es ist eine Typendeklaration. Es gibt aber noch keine Variable dieses Typs.

Sobald Sie im Programm tippen:

var

MeinObjekt: Stringfeld;

haben Sie ein Objekt angelegt. Es heißt "MeinObjekt". Der Aufruf der Funktionen von Stringfeld und der Zugriff auf Werte ergibt einen Fehler, denn diese existieren eben nur als Bauplan. Sie müssen also immer auf die Funktionen eines Objektes sich beziehen und dies hat eben den Namen "MeinObjekt":

MeinObjekt.setitem(5,'Hallo');

writeln(MeinObjekt.getitem(5));

Es sind nun die Funktionen (in der OOP Sprache: Methoden) des Objektes benutzt worden, der dazu auf den Bauplan Stringfeld zurückgreift.

Vererbung

Ein Vorteil von Objekten ist die Vererbung. Damit ist gemeint, das man von Stringfeld ein Objekt erstellen kann, das alles besitzt was schon stringfeld inne hat:
type
Stringfeld2 object
mstgringfeld : stringfeld;
index : integer;
end;

Bei diesem Objekt ist nur ein neues Feld hinzu gekommen. Stringfeld2 muss nun nicht die Methoden getitem und setitem definieren: Es besitzt diese schon, denn es hat sie von stringfeld geerbt welches ja ein Teil von stringfeld2 ist! Man kann auch Objekte unterschiedlichen Typs zueinander zuweisen, sofern man folgendes beachtet:

Ein zugewiesenes Objekt (rechts vom Gleichheitszeichen) muss immer das zuweisende Objekt (links vom Gleichheitszeichen) ausfüllen können:

var s1 : stringfeld;
s2 : stringfeld2;

begin
s2:=s1; {geht}
s1:=s2; {geht nicht}
end.

Stringfeld2 enthält Stringfeld1 und ein weiteres Feld. Mann kann daher S2:=s1 zuweisen, das Index Feld wird nicht verändert, weil dies kein Teil von Stringfeld1 ist. Der Umgekehrte Fall geht nicht, denn es existiert in s1 kein Index Feld, wo man den Wert von S2.index unterbringen könnte. Merkregel: Jeder "Sohn" kann Objekte eines "Vaters" aufnehmen. Ein "Vater" kann aber nie Sohnobjekte aufnehmen, da diese Felder enthalten können die er noch nicht besitzt.

Polymorphie

Polymorphie klingt fürchterlich ist aber ganz einfach: Es besagt nichts anderes als das jedes Objekt eigene Methoden hat und sich diese nicht mit anderen in die Quere kommen, die genauso heißen. So gibt es in Delphi in vielen Objekten eine ADD Methode die etwas anhängt - Eine Textzeile bei einem Textobjekt, Einen Listeneintrag bei einem listenobjekt, Einen Font bei einem Fontobjekt.

Dazu gehört auch das ein Objekt das von einem anderen abgeleitet ist, die geerbte Methode überschreiben kann und durch seine eigene ersetzen, aber im Bedarfsfall doch noch die des Vaters aufrufen kann.

Guter Programmierstill bei Objekten

Es ist in der objektorientierten Programmierung verpönt auf die Datenfelder selbst zuzugreifen, man bedient sich dazu der Methoden. Ein Beispiel haben Sie schon gesehen: Mit setitem und Getitem schreibt und liest man aus dem Feld. Dazu dienen zwei Schlüsselworte: public und private. Per definition ist alles von vornherein public, d.h. jeder kann von außen die Funktionen und Variablen nutzen. Alle Felder und Methoden die unter private deklariert wurden sind nach außen hin nicht sichtbar, können aber von Methoden des Objektes benutzt werden. Mit Public machen Sie Methoden des Objektes wieder nach außen hin sichtbar. Der Vorteil wird deutlich wenn Sie sich folgende Definition von Stringfeld ansehen:
interface
type
Stringfeld object
public
function
getitem(const i : integer): string;
procedure setitem(const i : integer; const item : string);
private
Feld : Array [1..100] of string;
{geändert nun in}
Feld : Array [1..100] of double;
end;

Hier müssten Sie die Routinen setitem und getitem so überarbeiten das sie einen string Wert in double konvertieren. Das wichtigste ist aber: Ihre Anwendung merkt von der Änderung des internen Datentyps nichts. Das ist hier ein etwas unsinniges Beispiel, aber oft gibt es beim Programmieren den Fall, das man ein Projekt anfängt und einen bestimmten Datentyp wie Word zur Speicherung von Artikelnummern auswählt. Dann plötzlich kommt der Kunde her und sagt "Tja aber wir haben die Artikel in Gruppen geordnet und 7 Stellige Nummern" - Essig ist es mit Word als Datentyp. Mit diesem Ansatz müssen sie nur die Routinen im Objekt ändern aber nicht im ganzen Programm alle Routinen überprüfen.

Sie sehen auch das die Routinen eines Objektes Eigenintelligenz haben sollten: Schon diese einfachen Routinen können überprüfen ob der Index in zulässigen Grenzen ist. Das ermöglicht es Ihnen ihre eigentlichen Programme schlank zu halten.

Komm schon!

Ausblick

Dies kann nur ein Einblick in die objektorientierte Programmierung sein. In Delphi werden diese ausgiebig benutzt. Dann gibt es auch noch Ereignismethoden, dynamische Objekte, Überschreiben und Überladen, virtuelle Methoden, Construktoren und Destruktoren, doch mit dem was sie hier mitbekommen haben sollten sie einen Einsteig in die Benutzung von Objekten in Delphi schaffen.

Gleichzeitig ist das Objektmodell in Delphi dem von Turbo Pascal überlegen. Hier haben wir z.B. eigene Funktionen für den Zugriff auf das Objekt definiert. Das müssen sie auch noch in Delphi, aber, man kann diese Funktionen mit den Datenelementen verbinden und dann können sie bei obiger Deklaration folgendes haben:

interface
type
Stringfeld class (TObject)
private
meinfeld : Array [1..100] of double;
function getitem(const i : integer): string;
procedure setitem(const i : integer; const item : string);
public
property
Feld : Array [1..100] of double read getitem; write setitem;
end;

Dann wäre ein Zugriff auf Feld wie bei einem normalen Array möglich - Alle Zugriffe gehen aber über die Funktionen, die Werte prüfen können z.B. ob der Index im Bereich 1..100 ist. Kurzum: Man hat die Möglichkeiten der objektorientierten Programmierung mit dem einfach lesbaren Quelltext verbunden. Das gibt es z.B. in C++ oder Java nicht. In Smalltalk kann man ähnliches erreichen weil dort die Namen von Funktionen genauso wie Variablen heißen dürfen. Allerdings ist bei Smalltalk ein Umdenken in eine völlig objektorientierte Welt nötig.

Wozu das ganze?

OOP ist eigentlich nicht mal so viel neues, wie man denkt. Es ist nur die Umsetzung von Forderungen in eine Programmiersprache. Diese Forderungen entstanden schon früh, als Software immer größer und unhandlicher wurde:

  1. Software soll als Black Box funktionieren: Man muss nicht wissen was intern passiert (Kapselung)
  2. Software soll modular sein - man soll definierte "Bausteine" wieder verwenden können (Modularität)
  3. Software soll unwesentliches "verbergen" (Information Hiding)
  4. Software soll definierte Schnittstellen haben

Einiges davon kennen Sie schon aus früheren Teilen dieses Kurses: Units verbergen Funktionen die nicht in dem Interface Teil stehen, funktionen lassen eine Interaktion nur über Ein/Ausgabeparameter zu.

OOP geht noch weiter und stellt folgende Anforderungen:

  1. sie sollten nie direkt auf Datenfelder zugreifen können - diese sind private. Sie greifen nur über Funktionen auf die Datenfelder zu. In reinen OOP Sprachen wie z.B. Smalltalk ist von außen nur über Methoden auf Datenfelder zugreifbar. In Pascal können Sie selbst es festlegen.
  2. Sie sollten Objekte so modellieren das sie durch Ableiten spezialisierter Nachkommen erzeugen können - also nicht zu viel Spezialfunktionen hineinpacken
  3. Objekte sollten nur Funktionen haben die ihre eigenen Daten bearbeiten oder diese in andere umwandeln.

Das ganze klingt sehr kleinlich hat aber wirklich Vorteile. Hier ein paar Beispiele:

  1. Beim Zugriff auf Arrays haben sie durch Funktionen die Kontrolle, ob jemand bei einem array [1..10] auf das 12.te Element zugreifen will. Allgemein gibt es nur sehr wenige einfache Daten die nicht irgendwie nachgeprüft werden müssen.
  2. Ein sehr spezialisierte Objekt hat ein Problem, wenn man es in leicht anderer Form benötigt. Man muss dann praktisch ein neues Objekt schreiben. Daher entwirft man oft einen einfachen Typ, der eigentlich selbst nie benutzt wird, aber von dem neue Typen abgeleitet werden. So könnte von einem Objekt eines generischen Zahlentyps für Finanzrechnungen ein Nachfahr mit double Feldern und einer mit Comp Feldern entstehen.
  3. Zum dritten ist zu sagen, das Objekte eben Bausteine sein sollen. Sobald Objekte anfangen globale Daten anzulegen, Funktionen aufzunehmen die nichts mit ihren Daten zu tun haben sind es keine Bausteine mehr. Die Universalität leidet.

Zum Thema Computer ist auch von mir ein Buch erschienen. "Computergeschichte(n)" beinhaltet, das was der Titel aussagt: einzelne Episoden aus der Frühzeit des PC. Es sind Episoden aus den Lebensäufen von Ed Roberts, Bill Gates, Steve Jobs, Stephen Wozniak, Gary Kildall, Adam Osborne, Jack Tramiel und Chuck Peddle und wie sie den PC schufen.

Das Buch wird abgerundet durch eine kurze Erklärung der Computertechnik vor dem PC, sowie einer Zusammenfassung was danach geschah, als die Claims abgesteckt waren. Ich habe versucht ein Buch zu schreiben, dass sie dahingehend von anderen Büchern abhebt, dass es nicht nur Geschichte erzählt sondern auch erklärt warum bestimmte Produkte erfolgreich waren, also auf die Technik eingeht.

Die 2014 erschienene zweite Auflage wurde aktualisiert und leicht erweitert. Die umfangreichste Änderung ist ein 60 Seiten starkes Kapitel über Seymour Cray und die von ihm entworfenen Supercomputer. Bedingt durch Preissenkungen bei Neuauflagen ist es mit 19,90 Euro trotz gestiegenem Umfang um 5 Euro billiger als die erste Auflage. Es ist auch als e-Book für 10,99 Euro erschienen.

Mehr über das Buch auf dieser eigenen Seite.

Sitemap Kontakt Neues Hier werben Bücher vom Autor Buchempfehlungen Top 99