25.02.2013 Aufrufe

Objektorientierte Programmiersprachen am Beispiel Eiffel - Software ...

Objektorientierte Programmiersprachen am Beispiel Eiffel - Software ...

Objektorientierte Programmiersprachen am Beispiel Eiffel - Software ...

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

<strong>Objektorientierte</strong><br />

<strong>Progr<strong>am</strong>miersprachen</strong><br />

<strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong><br />

Referat im Rahmen des Seminars<br />

„<strong>Progr<strong>am</strong>miersprachen</strong>“<br />

24. Mai 2004<br />

Jan Griesel<br />

Prof. Dr. Claudia Leopold, Dipl.-Inf. Michael Süß<br />

Fachgruppe <strong>Progr<strong>am</strong>miersprachen</strong>/ -methodik<br />

Fachbereich Elektrotechnik / Informatik<br />

Universität Kassel


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 1 -<br />

Inhalt<br />

Inhalt ..............................................................................................1<br />

1. Einführung <strong>Eiffel</strong> .......................................................................2<br />

2. <strong>Objektorientierte</strong> Progr<strong>am</strong>mierung..............................................3<br />

2.1 Einführung ............................................................................3<br />

2.2 Klassen und Objekte ..............................................................3<br />

2.3 Typen und Verweise ...............................................................4<br />

2.4 Generalisierung, Vererbung.....................................................5<br />

2.5 Datenkapselung.....................................................................5<br />

2.6 Redefinition...........................................................................7<br />

2.7 Polymorphismus, dyn<strong>am</strong>isches Binden......................................8<br />

2.8 Abstrakte Klassen ..................................................................9<br />

2.9 Par<strong>am</strong>etrisierbare Klassen.......................................................9<br />

2.10 Multiple Vererbung ............................................................ 10<br />

2.11 Wiederholtes Erben ........................................................... 10<br />

2.12 Zusicherung, Design-by-Contract ........................................ 11<br />

3.<br />

4.<br />

5.<br />

6.<br />

Weitere Besonderheiten........................................................... 12<br />

<strong>Eiffel</strong><br />

Einsatzgebiete........................................................................ 12<br />

Fazit ..................................................................................... 12<br />

Literatur ................................................................................ 13


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 2 -<br />

1. Einführung <strong>Eiffel</strong><br />

<strong>Eiffel</strong> ist eine reine objektorientierte Progr<strong>am</strong>miersprache, welche seit<br />

1985 von dem französischen Informatiker Bertrand Meyer und seiner<br />

Firma Interactive <strong>Software</strong> Engeneering Inc. (Goleta, Kalifornien) als<br />

Alternative zu C++ entworfen wurde. Seinen N<strong>am</strong>en verdankt <strong>Eiffel</strong> dem<br />

in der zweiten Hälfte des 19. Jahrhunderts bekannt gewordenen Ingenieur<br />

Gustave <strong>Eiffel</strong>, Erbauer des <strong>Eiffel</strong>turms (erbaut 1887-1889) in Paris. Der<br />

N<strong>am</strong>e <strong>Eiffel</strong> stellt den Anspruch in den Vordergrund, eine Sprache zu<br />

geschaffen, mit der <strong>Software</strong>entwicklung gemäß den Standards des<br />

Ingenieurwesens ermöglicht wird.<br />

Bei <strong>Eiffel</strong> handelt es sich im Unterschied zu C++ um einen vollständig<br />

neuen Entwurf, der lediglich in Anlehnung an ältere Sprachen (Ada 1 und<br />

der ALGOL-Sprachf<strong>am</strong>ilie 2 ) aufgebaut wurde.<br />

Ziel der Entwicklung von <strong>Eiffel</strong> ist es, eine Sprache zu erschaffen, mit der<br />

es möglich ist umfangreiche <strong>Software</strong>projekte aus zuverlässigen, wieder<br />

verwendbaren und leicht wartbaren Modulen zu konstruieren. Um dies zu<br />

erreichen, wurden riskante Möglichkeiten, wie manuelle<br />

Speicherverwaltung, globale Variablen, GOTOs, etc. komplett<br />

ausgeschlossen.<br />

Besonderheiten von <strong>Eiffel</strong> sind u.a. Zusicherung (Desing-by-Contract) und<br />

Multiple Vererbung.<br />

Die Sprachdefinition von <strong>Eiffel</strong> ist Public-Domain und steht unter der<br />

Kontrolle von Nonprofit International Consortium for <strong>Eiffel</strong> (NICE) 3 ,<br />

welches sich das Recht vorbehält, jedes Entwicklerwerkzeug bezüglich der<br />

Konformität zum Standard zu validieren.<br />

Es existieren wenige kommerzielle <strong>Eiffel</strong>-Entwicklungsumgebungen und<br />

mit Smart<strong>Eiffel</strong> 4 zumindest ein OpenSource-Compiler. Die Sprache konnte<br />

bisher nicht an den Verbreitungsgrad von Java oder C++ heranreichen.<br />

<strong>Eiffel</strong> besitzt keine größere <strong>Software</strong>- oder IT-Firma, von welches es<br />

unterstützt wird, wie z.B. Java durch Sun.<br />

<strong>Eiffel</strong><br />

1<br />

Ada ist eine strukturierte Progr<strong>am</strong>miersprache mit statischer Typenbindung. Sie<br />

wurde in den 1970er Jahren von Jean Ichbiah entworfen.<br />

2<br />

ALGOL wurde von 1958-1963 entwickelt und diente zur Lösung<br />

wissenschaftlich-numerischer Probleme.<br />

3 NICE http://eiffel-nice.org<br />

4 <strong>Eiffel</strong> Compiler unter GNU http://smarteiffel.loria.fr


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 3 -<br />

2. <strong>Objektorientierte</strong> Progr<strong>am</strong>mierung<br />

Dieser Themenbereich ist in mehrere Unterpunkte gegliedert, welche in<br />

sich wiederum in der folgenden Art untergliedert wurden. Zuerst erfolgt<br />

eine kurze allgemeine Definition zu dem Themenkomplex, darauf wird die<br />

Umsetzung in der Progr<strong>am</strong>miersprache <strong>Eiffel</strong> erläutert und schließlich<br />

werden die Unterschiede zur Umsetzung in der Progr<strong>am</strong>miersprache Java<br />

aufgelistet.<br />

2.1 Einführung<br />

Die Idee der Objektorientierung ist fast 30 Jahre alt. In den 90er Jahren<br />

war die objektorientierte Progr<strong>am</strong>mierung (Abkürzung OOP) das führende<br />

Progr<strong>am</strong>mierparadigma. Viele der heute verwendeten<br />

<strong>Progr<strong>am</strong>miersprachen</strong> sind entweder von Grund auf objektorientiert (wie<br />

<strong>Eiffel</strong>, Java, SmallTalk) oder wurden im Laufe der Zeit mit<br />

objektorientierten Erweiterungen versehen (Basic, Pascal, ADA).<br />

2.2 Klassen und Objekte<br />

Bei der objektorientierten Progr<strong>am</strong>mierung werden Daten und die auf<br />

diese Daten anzuwendenden Operationen als Klassen zus<strong>am</strong>mengefasst.<br />

Ein Objekt ist ein Exemplar (auch Instanz genannt) einer Klasse, es<br />

enthält durch Attribute repräsentierte Informationen, deren Struktur in<br />

der Klasse definiert ist. Im Progr<strong>am</strong>mablauf kommunizieren die Objekte<br />

miteinander, indem ein Objekt die Attribute eines anderen Objektes auf<br />

bestimmte Eigenschaften hin abfragt oder es beauftragt, eine bestimmte<br />

Operation mit einem bestimmten Datenwert auszuführen.<br />

In <strong>Eiffel</strong> besteht ein Progr<strong>am</strong>m nur aus Klassen. Zur Laufzeit werden<br />

Exemplare der Klassen, die Objekte, erzeugt.<br />

class NAME<br />

<strong>Eiffel</strong><br />

end – class NAME<br />

creation<br />

...<br />

feature<br />

...


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 4 -<br />

Die Eigenschaften von Objekten werden durch Attribute angegeben. Das<br />

Verhalten von Objekten wird durch Methoden definiert. Attribute und<br />

Methoden werden im Abschnitt features definiert.<br />

Der Bereich creation ist optional. In ihm werden Methoden, aus dem<br />

Bereich feature aufgelistet, welche zu Initialisierung eines Objektes<br />

wichtig sind.<br />

In <strong>Eiffel</strong> werden Klassen meist erstellt, um einen abstrakten Datentyp zu<br />

beschreiben. Ein abstrakter Datentyp stellt Schnittstellen zur Verfügung,<br />

welche bestimmte Aufgaben erfüllen. Es ist jedoch nicht bekannt, wie<br />

diese Aufgaben erfüllt werden. Detaillierter wird auf diesen Punkt im<br />

Bereich Datenkapselung 2.5 eingegangen.<br />

Ein Unterschied zu diesem Punkt zur ebenfalls objektorientierten<br />

Progr<strong>am</strong>miersprache Java ist der, dass Attribute und Methoden nicht, wie<br />

in <strong>Eiffel</strong>, zu features zus<strong>am</strong>mengefasst werden. Ein Java Progr<strong>am</strong>m<br />

benötigt eine Klasse, welche als Hauptprogr<strong>am</strong>m-Klassen fungiert, mit<br />

einer main-Methode. Bei <strong>Eiffel</strong> wird dies durch die (hier) root-Klasse<br />

genannte Klasse erledigt, diese enthält im Abschnitt creation eine<br />

bestimmt Prozedur.<br />

2.3 Typen und Verweise<br />

Ein Typ spezifiziert das Verhalten einer Menge von Objekten.<br />

In objektorientierten Sprachen muss grundsätzlich unterschieden werden<br />

zwischen dem statischen Typ (bzw. der statischen Klasse) eines Objektes,<br />

womit der Typ gemeint ist, den der Compiler herleiten kann, und dem<br />

dyn<strong>am</strong>ischen Typ (bzw. der dyn<strong>am</strong>ischen Klasse), welcher den Typ des<br />

Objektes zur Laufzeit eines Progr<strong>am</strong>ms tatsächlich besitzt.<br />

<strong>Eiffel</strong> ist eine statisch getypte Sprache. Dies bedeutet, dass jedes feature<br />

einer Klasse mit einem eindeutigen Datentyp deklariert werden muss.<br />

class REFERAT<br />

feature<br />

autor: PERSON;<br />

titel: STRING;<br />

seitenzahl: INTEGER;<br />

end – class REFERAT<br />

Die Attribute titel und seitenzahl werden mit den vordefinierten<br />

<strong>Eiffel</strong><br />

Datentypen STRING und INTEGER definiert. Das Attribut autor hat als<br />

Datentyp die Klasse Person. Diese Deklaration bedeutet, dass die zum<br />

Attribut autor gehörende Komponente eines Referatobjektes ein Verweis<br />

auf ein Objekt vom Typ PERSON ist.<br />

Es gibt in <strong>Eiffel</strong> nur zwei Arten von Datentypen: einfache Typen (INTEGER,<br />

BOOLEAN, CHARACTER, REAL und DOUBLE) und Klassentypen.


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 5 -<br />

Klassentypen müssen durch Klassendeklarationen definiert werden und<br />

gehören nicht zum Basistypsystem von <strong>Eiffel</strong>.<br />

2.4 Generalisierung, Vererbung<br />

Bei der Generalisierung werden Eigenschaften hierarchisch gegliedert,<br />

wobei Eigenschaften mit allgemeinerer Bedeutung (allgemeineren)<br />

Oberklassen zugeordnet und speziellere Eigenschaften solchen Klassen<br />

zugeordnet werden, welche den Oberklassen untergeordnet sind. Die<br />

Eigenschaften der Oberklassen werden an die Unterklassen weitergegeben<br />

oder vererbt. Die Unterklasse verfügt somit über ihre spezifizierten<br />

Eigenschaften als auch den Eigenschaften ihrer Oberklasse(n).<br />

Eine Vererbung von einer Oberklasse an mehrere Unterklassen ist<br />

möglich, ein gleichzeitiges erben von mehreren Oberklassen fällt in den<br />

Bereich Multiple Vererbung 2.10.<br />

Die Grafik zeigt eine Klassenhierarchie, wobei die Klasse Oberklasse eine<br />

Generalisierung der Klasse Ober-Oberklasse darstellt und selbst von den<br />

Klassen Unterklasse 1 und Unterklasse 2 geerbt wird.<br />

Generalisierung wird in <strong>Eiffel</strong> so umgesetzt, dass zu Beginn der Definition<br />

einer Klasse in einer Erbklausel die jenige Klasse angegeben wird, von<br />

welcher Eigenschaften geerbt werden sollen. Die Eigenschaften (features)<br />

der Oberklasse müssen nicht erneut im feature-Bereich genannt werden,<br />

da sie automatisch verfügbar sind. Lediglich die Eigenschaften die neu<br />

hinzukommen müssen im feature-Bereich explizit benannt werden.<br />

<strong>Eiffel</strong><br />

In Java ist dieser Vorgang bis auf eine andere Form der Notation gleich.<br />

2.5 Datenkapselung<br />

Unter Kapselung versteht man selbstständige Progr<strong>am</strong>mmodule, die<br />

sowohl Daten (Attribute) als auch deren Verarbeitungsroutinen


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 6 -<br />

(Methoden) enthalten. Die Datenstruktur eines gekapselten Objektes<br />

bleibt verborgen. Zugriff auf das Objekt kann nur über öffentlich sichtbare<br />

Attribute oder Methoden genommen werden.<br />

Datenkapselung ist besonders im Zus<strong>am</strong>menhang mit Generalisierung<br />

oder Vererbung besonders wichtig. Ziel ist es nur die Informationen zur<br />

Verfügung zu stellen, welche für die Funktion einer Unterklasse dringend<br />

nötig sind.<br />

<strong>Eiffel</strong> bietet hierbei besondere Möglichkeiten, die es in Java in dieser Art<br />

nicht gibt. So ist es in <strong>Eiffel</strong> möglich nur bestimmte geerbte Eigenschaften<br />

an eine weitere Unterklasse zu exportieren. Hierfür gibt es direkt unter der<br />

Erbklausel einen export-Bereich, in welchem jene Eigenschaften der<br />

Oberklasse einzeln benannt werden, welche zus<strong>am</strong>men mit den neuen<br />

Eigenschaften in der Unterklasse verfügbar sein sollen. Ist dieser Bereich<br />

nicht vorhanden, so sind alle Eigenschaften in der Unterklasse verfügbar.<br />

Diese Methode der Zugriffsbeschränkung auf Eigenschaften der<br />

Oberklasse durch Unterklassen wurde während der Entwicklung von <strong>Eiffel</strong><br />

noch weiter verfeinert. So ist es nun sogar möglich explizit zu den<br />

Eigenschaften, welche exportiert werden sollen, auch eine Unterklasse<br />

anzugeben, an welche die Eigenschaften vererbt werden sollen. Statt<br />

hierbei alle zu vererbenden Eigenschaften einzeln aufzuzählen, kann auch<br />

ein Schlüsselwort (all) angegeben werden, so dass alle Eigenschaften<br />

vererbt werden. Ist bei dieser Exportmethode eine Unterklasse nicht<br />

genannt, so werden keine Eigenschaften der Oberklasse an diese vererbt,<br />

außer den neuen Eigenschaften der vererbenden Klasse selbst. Ist eine<br />

Eigenschaft für eine Unterklasse freigegeben, so steht sie auch<br />

automatisch allen Unterklassen dieser Unterklasse zur Verfügung, sofern<br />

der Export nicht in einer anderen Unterklasse eingeschränkt wird.<br />

In Java wird eine Zugriffskontrolle realisiert, indem jedes Attribut und jede<br />

Methode mittels der Angaben public, private, protected und package bei<br />

der Initialisierung klassifiziert wird. Die einzelnen Angaben Regeln wir<br />

folgt:<br />

- public: Auf Komponenten mit diesem Zugriffsrecht kann man<br />

überall dort zugegriffen, wo man auf die Klasse zugreifen kann, in<br />

der sie definiert sind.<br />

- private: Auf private Komponenten kann man nur innerhalb der<br />

Klasse zugreifen, in der sie definiert sind.<br />

- protected: Auf Komponenten mit diesem Zugriffsrecht kann man<br />

innerhalb des Paketes (package), das die Klasse enthält, in der<br />

sie definiert sind, und in Unterklassen, zugreifen.<br />

- package: Auf Komponenten ohne ein Zugriffsrecht-Attribut kann<br />

man innerhalb des Paketes, das die Klasse enthält, in der sie<br />

definiert sind, zugreifen.<br />

<strong>Eiffel</strong><br />

und Methoden keine explizite Nennung von Erben geben. Stattdessen<br />

Wie man deutlich erkennen kann ist der Ansatz der Zugriffssteuerung in<br />

Java im Vergleich zu <strong>Eiffel</strong> eher indirekt. Es kann oder muss für Attribute


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 7 -<br />

werden durch die Vergabe der Zugriffsrecht-Attribute Gruppen definiert,<br />

welche Zugriff auf eine bestimmte Eigenschaft haben.<br />

2.6 Redefinition<br />

Unter Redefinition versteht man die Veränderung der Implementierung<br />

geerbter Eigenschaften. So können geerbte Methoden überschrieben<br />

werden, sofern man die Berechtigung dazu hat.<br />

Um den Sinn dieser Möglichkeit besser zu verdeutlichen, dient dieses<br />

<strong>Beispiel</strong>. Nehmen wir an in einer Firmenfinanzsoftware existiert eine<br />

Klasse Mitarbeiter, welche u.a. das Gehalt eines Mitarbeiters zur<br />

Verfügung stellen kann. Durch die Schaffung eines neuen Arbeitsbereiches<br />

in der Firma kommt es zu Neueinstellungen besonderer Angestellter,<br />

welche nach Leistung vergütet werden sollen. Dazu wird eine neue Klasse<br />

Leistungsmitarbeiter erstellt, welche eine Unterklasse der Klasse<br />

Mitarbeiter ist. In dieser Unterklasse wird nun die Methode, welche das<br />

Gehalt der Mitarbeiter errechnet durch eine neu Methode, welche auf<br />

einem anderen Rechenschlüssel basiert, ersetzt.<br />

<strong>Eiffel</strong> ermöglicht es geerbte Eigenschaften neu zu definieren. Hierzu wird<br />

in dem redefine-Bereich angegeben, welche der geerbten Eigenschaften<br />

(features) verändert werden. Jedes dieser features muss nun erneut als<br />

feature der Klasse im eigenen feature-Bereich deklariert und später<br />

implementiert werden.<br />

class LEISTUNGSMITARTBEITER<br />

inherit MITARBEITER<br />

redefine<br />

gehalt<br />

export<br />

{ARBEITGEBER} n<strong>am</strong>e, vorn<strong>am</strong>e, adresse;<br />

{FINANZAMT} all<br />

end<br />

feature<br />

abteilung: STRING;<br />

raum, telefon: INTEGER;<br />

gehalt: REAL is -- Gehalt berechnen<br />

do Result := Gehalt nach Leistung<br />

end<br />

end -- class LEISTUNGSMITARTBEITER<br />

<strong>Eiffel</strong><br />

Die dargestellte Vererbung mit Redefinition zeigt eine Deklaration der<br />

Klasse aller Leistungsmitarbeiter, in der das feature gehalt neu definiert<br />

wurde. Ohne den redefine-Bereich wäre die erneute Deklaration von<br />

gehalt als Merkmal von Leistungsmitarbeiter ein Fehler, da gehalt<br />

bereits aus der Klasse Mitarbeiter übernommen wird.


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 8 -<br />

Der redefine-Bereich teilt mit, welche features einer Oberklasse in einer<br />

Unterklasse neu definiert werden. Hierdurch wird gewährleistet, dass der<br />

selbe N<strong>am</strong>e sich auf verschiedene aktuelle features beziehen kann.<br />

Abhängig vom Typ des Objektes, auf das es angewandt wird, erhält man<br />

eine andere Implementierung.<br />

Es ist nicht möglich ein feature beliebig abzuändern. Von außen betrachtet<br />

muss ein feature im Wesentlichen unverändert, d.h. auf die gleiche Art<br />

aufrufbar und veränderbar, bleiben. Die Vereinbarungen der Oberklasse<br />

müssen weiterhin Gültigkeit haben.<br />

Zu den Vereinbarungen, die von der Oberklasse übernommen werden<br />

müssen, gehören insbesondere die Anzahl der Argumente und die Typen<br />

der features. Routinen müssen Routinen bleiben und Attribute Attribute.<br />

In Java ist eine Redefinierung durch eine Unterklasse ebenfalls möglich.<br />

Attribute und Methoden dürfen sogar umdefiniert und überladen (siehe<br />

Abschnitt 2.7) werden, sofern die Zugriffsrechte dies zulassen. Mit dem<br />

Attribut final kann man verhindern, dass eine Methode in Unterklassen<br />

verändert wird. Dies schließt aber nicht aus, dass sie in der Unterklasse<br />

noch benutzt werden kann. Auch Attribute können mit final deklariert<br />

werden. Ein derartiges Attribut erhält genau einmal einen Wert, und zwar<br />

durch die Initialisierung.<br />

2.7 Polymorphismus, dyn<strong>am</strong>isches Binden<br />

Polymorphismus (Vielgestaltheit) bezeichnet im Allgemeinen die Fähigkeit,<br />

verschiedene Formen anzunehmen. Bezogen auf die Objektorientierung<br />

bedeutet Polymorphie und dyn<strong>am</strong>isches Binden, dass in einer<br />

Klassenhierarchie gleichn<strong>am</strong>ige Operationen für verschiedene<br />

Unterklassen unterschiedlich implementiert sein können. Objekte können<br />

polymorph sein, d.h. die zum jeweiligen Kontext passende Operation zur<br />

Verfügung stellen. Wenn für ein einzelnes Objekt die spezifisch<br />

anwendbare Operation erst zu Laufzeit ausgewählt wird, spricht man von<br />

Operationen, welche dyn<strong>am</strong>isch zu den Objekten gebunden werden.<br />

<strong>Eiffel</strong> bietet Polymorphismus durch die Möglichkeit, Eigenschaften von<br />

Klassen teilweise oder auch ganz zu redefinieren. Durch dyn<strong>am</strong>isches<br />

Binden wird dann zur Laufzeit ermittelt, welche der redefinierten<br />

Versionen (d.h. welche konkrete Implementierung) tatsächlich ausgeführt<br />

werden soll. Eine Zuweisung der Form a := b ist in <strong>Eiffel</strong> zulässig, nicht<br />

nur wenn a und b vom selben Typ sind, sondern auch, wenn b Instanz<br />

einer Unterklasse der Klasse von a ist.<br />

<strong>Eiffel</strong><br />

gleichen N<strong>am</strong>en, können sich aber z.B. in der Art der Übergabewerte<br />

Java bietet ebenfalls Polymorphismus, hier jedoch durch überladen von<br />

Methoden. Das Überladen ist im Grunde eine Redefinierung einer geerbten<br />

Methode mit dem Unterschied, dass mehrere Versionen der redefinierten<br />

Methode in einer Klasse vorkommen können. Alle Versionen haben den


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 9 -<br />

unterscheiden. Es bleibt dem Compiler überlassen, die richtige Version für<br />

eine bestimmte Gelegenheit auszuwählen.<br />

2.8 Abstrakte Klassen<br />

Die Methoden in einer abstrakten Klasse sind nur durch die Definition der<br />

Vor- und Nachbedingung definiert. Die Methoden wurden ohne eigentliche<br />

Operation implementiert. Diese wird in einer abgeleiteten Klasse<br />

implementiert, die Implementierung der eigentlichen Operation wurde also<br />

aufgeschoben. Von abstrakten Klassen werden keine Objekte erzeugt.<br />

In <strong>Eiffel</strong> gilt eine Methode als aufgeschoben (deferred), wenn an stelle der<br />

Anweisungsfolge das Schlüsselwort deferred enthalten ist.<br />

Eine Klasse gilt als deferred, wenn sie eine Methode enthält die<br />

aufgeschoben ist oder eine aufgeschobene Methode erbt und nicht<br />

redefiniert hat. Eine solche Klasse muss in ihrer Deklaration als deferred<br />

class gekennzeichnet sein.<br />

Auch in Java können abstrakte Klassen verwendet werden. Die<br />

Realisierung ist gleich der in <strong>Eiffel</strong>. Java verwendet bei der Deklaration von<br />

abstrakten Klassen und Methoden das Schlüsselwort abstract.<br />

2.9 Par<strong>am</strong>etrisierbare Klassen<br />

Eine par<strong>am</strong>etrisierbare Klasse (synonym zu generische Klasse) ist eine mit<br />

generischen formalen Par<strong>am</strong>etern versehene Schablone, mit der<br />

gewöhnliche (nicht-generische) Klassen erzeugt werden können. Die<br />

generischen Par<strong>am</strong>eter dienen als Stellvertreter für die aktuellen<br />

Par<strong>am</strong>eter, die Klassen oder einfache Datentypen repräsentieren.<br />

Par<strong>am</strong>etrisierte Klassen sind keine Typen, sondern Typschemata. Erst mit<br />

den aktuellen Par<strong>am</strong>etern werden sie zu Typen. Ohne aktuelle Par<strong>am</strong>eter<br />

kann man ihre Merkmale nicht ausführen und auch nicht austesten.<br />

In <strong>Eiffel</strong> werden generische Klassen erzeugt, indem bei der<br />

Klassendeklaration hinter den Klassenn<strong>am</strong>en in eckigen Kl<strong>am</strong>mern durch<br />

Kommata getrennt formale generische Par<strong>am</strong>eter angegeben werden.<br />

class GENERISCHEKLASSE[X]<br />

...<br />

<strong>Eiffel</strong><br />

testaufruf: GENERISCHEKLASSE[INTEGER]<br />

Innerhalb der Klasse kann ein formaler generischer Par<strong>am</strong>eter in allen<br />

Deklarationen wie ein normaler Datentyp eingesetzt werden, sei es als Typ<br />

von Attributen, Methoden, Par<strong>am</strong>etern in Routinen oder von lokalen<br />

Variablen. Nach außen ist der formale generische Par<strong>am</strong>eter unbekannt.


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 10 -<br />

Ein <strong>Beispiel</strong> bei dem die Anwendung gerischer Klassen sinnvoll ist, wäre<br />

ein Listenvergleich. In der generischen Klasse würde dazu eine Methoden<br />

Implementiert werden, welche z.B. zwei Elemente verschiedener Listen<br />

auf Übereinstimmung vergleicht. Durch die Übergabe eines aktuellen<br />

Par<strong>am</strong>eters bei dem Erbvorgang, wird der Datentyp der Elemente<br />

übergeben, welche verglichen werden sollen.<br />

Par<strong>am</strong>etrisierbare Klassen lassen sich nur über Umwege in Java<br />

realisieren. Eine vollständige Implementierung ist in Planung.<br />

2.10 Multiple Vererbung<br />

Wenn eine Unterklasse mehrere direkte Oberklassen hat, spricht man von<br />

multipler Vererbung.<br />

Multiple Vererbung lässt sich in <strong>Eiffel</strong> realisieren. In der Vererbungsklausel<br />

werden dazu mehrere Oberklassen zus<strong>am</strong>men mit eventuellen<br />

Modifikationen geerbter features angegeben.<br />

Erbt eine Klasse direkt von mehreren Klassen, so hat sie direkt Zugriff auf<br />

alle features der Oberklassen. Dies kann in manchen Fällen zu<br />

N<strong>am</strong>enskonflikten führen. <strong>Eiffel</strong> umgeht dies, indem durch Erbung<br />

vorhandene features mit gleichem N<strong>am</strong>en umbenannt werden müssen.<br />

Laut Meinung der Java Entwickler führe Multiple Vererbung nur zu<br />

„unnötigen“ Problemen. Daher können Unterklassen immer nur eine<br />

Oberklasse haben. Java hat also nur einfacher Vererbung.<br />

2.11 Wiederholtes Erben<br />

Durch die Möglichkeit der multiplen Vererbung ist eine mehrfache Erbung<br />

der gleichen Klasse<br />

<strong>Eiffel</strong><br />

möglich.


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 11 -<br />

Bei wiederholtem<br />

Erben von gleichen<br />

Oberklassen ergibt<br />

sich das Problem,<br />

dass die features der<br />

mehrfach geerbten<br />

Klasse ebenfalls<br />

mehrfach vorhanden<br />

sind. Im letzten<br />

Abschnitt wurde<br />

erklärt, dass hierbei<br />

ein N<strong>am</strong>enskonflikt<br />

auftritt, welcher durch Umbenennung doppelter features mit gleichem<br />

N<strong>am</strong>en gelöst wird. Dieses Vorgehen macht bei einer wiederholten Erbung<br />

nur dann Sinn, wenn die features nicht gleich sind, also wenn sie von<br />

einer Oberklasse, welche die features wiederum geerbt hat, redefiniert<br />

oder umbenannt wurden. Ist dies nicht der Fall und sind die features<br />

vollkommen identisch, so werden sie als ein feature betrachtet und<br />

vereinigt.<br />

2.12 Zusicherung, Design-by-Contract<br />

Eine wichtige Möglichkeit, die Gefahr von Abweichungen zwischen<br />

<strong>Software</strong>-Spezifikationen und ihren Implementierungen zu vermindern, ist<br />

die Einführung von Spezifikationselementen in die Implementierung. Dazu<br />

werden Klassen, Methoden oder Attributen Ausdrücke über den Zweck<br />

dieses Elements zugeordnet. Ein solcher Ausdruck, welcher mögliche<br />

Zustände eines solchen Elements angibt wird Zusicherung (Design-by-<br />

Contract oder Progr<strong>am</strong>ming-by-Contract) genannt.<br />

In <strong>Eiffel</strong> existieren zur Implementierung solcher Zusicherungen eigene<br />

Prädikate (and, or, and then, or else, not, xor, implies), welche<br />

ausschließlich für diese Zusicherungen eingeführt wurden.<br />

Zusicherungen stellen in <strong>Eiffel</strong> boolsche-Ausdrücke dar.<br />

n>0 and not x=Void<br />

Dieser boolsche-Ausdruck wird dann erfüllt, wenn n größer 0 und x nicht<br />

leer ist.<br />

Es ist möglich die Zusicherungen während der Laufzeit überwachen zu<br />

lassen. Kommt es durch nicht erfüllte Zusicherungen zu einem Fehler,<br />

kann die Routine entweder selbst innerhalb eines rescue-Bereichs<br />

versuchen diesen<br />

<strong>Eiffel</strong><br />

Fehler zu beheben oder dieser Fehler wird an die<br />

aufgerufene Routine zurückgeben, um dort eine Fehlerbehandlung zu<br />

ermöglichen.


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 12 -<br />

3. Weitere Besonderheiten<br />

<strong>Eiffel</strong> Quelltext wird gewöhnlich in Maschinencode (Binär) der<br />

Zielmaschine kompiliert. Es besteht aber auch die Möglichkeit der<br />

Umwandlung von <strong>Eiffel</strong>-Souce in C-Code. Zudem gibt es die Ansätze<br />

diesen in Bytecode für Java Virtual Machine zu übersetzen.<br />

Zur Entstehungszeit von <strong>Eiffel</strong> war es üblich die Speicherverwaltung für<br />

eine Anwendung manuell zu Implementieren. Ähnlich wie bei Smalltalk<br />

stellt <strong>Eiffel</strong> den benötigten Speicher automatisch zu Verfügung. Die<br />

Freigabe von nicht mehr benötigtem Speicherplatz wird mittels des<br />

garbage-collector, ebenfalls ein automatisierten Vorgang, realisiert.<br />

4. Einsatzgebiete<br />

Für <strong>Eiffel</strong> werden als Anwendungsgebiete, für welche es sich besonders<br />

anbieten soll genannt:<br />

- sicherheitskritische Anwendungen<br />

- Entwurf- und Spezifikationssprachen<br />

- Ausbildung in objektorientierter Progr<strong>am</strong>mierung<br />

(Die Angaben sind Aussagen der <strong>Eiffel</strong> Entwickler selbst und können an<br />

dieser Stelle nicht bestätigt oder verworfen werden.)<br />

5. Fazit<br />

Während meiner Arbeit an diesem Referat und dem dadurch gewonnenem<br />

Eindruck bezüglich der Möglichkeiten von <strong>Eiffel</strong>, bin ich zu der<br />

Überzeugung gelangt, dass <strong>Eiffel</strong> die Kriterien erfüllt, auf Grund welchen<br />

<strong>Eiffel</strong> erschaffen wurde. <strong>Eiffel</strong> ist vollkommen objektorientiert und dank<br />

seiner ausgefeilten Datenkapselungsmöglichkeiten (spezifischer feature-<br />

Export) ist ein hohes Maß an Sicherheit gewährleistet. Auch sind<br />

Eigenschaften moderner Sprachen, wie automatische Speicherverwaltung<br />

oder die Möglichkeit der Zusicherung in <strong>Eiffel</strong> bereits implementiert.<br />

Ich persönlich halte die Möglichkeit der multiplen Vererbung für eine<br />

unnötige Quelle von<br />

<strong>Eiffel</strong><br />

Fehlern. Die bei sehr großen Projekten eine sehr gute<br />

Planung voraussetzt, um solche zu vermeiden. In Java, welches multiple<br />

Vererbung nicht unterstützt, wird mithilfe von Schnittstellen erreicht, dass<br />

man Eigenschaften von mehreren Klassen erben kann. Ich halte diesen<br />

Ansatz für sinnvoller im Vergleich zur multiplen Vererbung.


<strong>Objektorientierte</strong> <strong>Progr<strong>am</strong>miersprachen</strong> <strong>am</strong> <strong>Beispiel</strong> <strong>Eiffel</strong> - 13 -<br />

6. Literatur<br />

Meyer, Bertrand: EIFFEL The language<br />

Prentice Hall International (UK) Ltd; 1992; I. Reprint<br />

ISBN: 0-13-247925-7<br />

Switzer, Robert: EIFFEL An Introduction<br />

Prentice Hall International (UK) Ltd; 1993; II. Series<br />

ISBN: 0-13-105909-2<br />

Oestereich, Bernd: <strong>Objektorientierte</strong> <strong>Software</strong>entwicklung<br />

R. Oldenbourg Verlag München Wien; 1998; 4. Auflage<br />

ISBN: 3-486-24787-5<br />

Gumm, Sommer: Einführung in die Informatik<br />

R. Oldenbourg Verlag München Wien; 2002; 5. Auflage<br />

ISBN: 3-486-25635-1<br />

Schildt, Herbert: Java 2 Ent-Packt<br />

MITP-Verlag GmbH, Bonn; 2001; 1. Auflage<br />

ISBN: 3-8266-0736-8<br />

<strong>Eiffel</strong>

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!