11.07.2015 Aufrufe

Übersetzung von OO-Sprachen

Übersetzung von OO-Sprachen

Übersetzung von OO-Sprachen

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.

Westfälische Wilhelms-Universität MünsterAusarbeitungÜbersetzung <strong>von</strong> <strong>OO</strong>-<strong>Sprachen</strong>im Rahmen des Seminars Übersetzung <strong>von</strong> künstlichen <strong>Sprachen</strong>Michael Bur am OrdeThemensteller: Prof. Dr. Herbert KuchenBetreuer: MScIS Tim MajchrzakInstitut für WirtschaftsinformatikPraktische Informatik in der Wirtschaft


Inhaltsverzeichnis1 Einleitung ................................................................................................................... 12 Objektorientierte Programmiersprachen .................................................................... 22.1 Einordnung ......................................................................................................... 22.2 Klassen- und objektorientiertes Sprachkonzept ................................................. 22.2.1 Objekte und Klassen ................................................................................... 22.2.2 Vererbungskonzept ..................................................................................... 32.2.3 Polymorphismus ......................................................................................... 63 Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong> ........................................................... 93.1 Reale und virtuelle Maschinen ........................................................................... 93.2 Übersetzung <strong>von</strong> Methoden ............................................................................. 113.3 Übersetzung <strong>von</strong> Vererbung ............................................................................ 123.3.1 Einfachvererbung ...................................................................................... 123.3.2 Mehrfachvererbungen ............................................................................... 133.4 Übersetzung <strong>von</strong> Parametrisierung .................................................................. 163.4.1 Kopiervariante .......................................................................................... 173.4.2 Echte generische Variante ........................................................................ 194 Zusammenfassung ................................................................................................... 215 Literaturverzeichnis ................................................................................................. 22II


Kapitel 1: Einleitung1 EinleitungDer Themenkomplex des Übersetzerbaus hat eine lange Tradition in dem Bereich derInformatik, wobei, bezogen auf das Alter der Thematik, in der letzten Zeit viel imBereich der Übersetzung <strong>von</strong> objektorientierten Programmiersprachen entwickeltwurde. Dies liegt mit unter daran, dass Softwaresysteme heutzutage immer größer unddamit komplexer werden und objektorientierte Programmierung als ein wesentlicherAnsatz angesehen wird, um diese Komplexität beherrschbarer zu machen.Objektorientierte Programmierung ermöglicht dies mit Hilfe <strong>von</strong> Modularisierung,Kapselung, Erweiterbarkeit und Wiederverwendbarkeit der Programmierungen.Objektorientierte Programmierung hat viele Gemeinsamkeiten mit der imperativenProgrammierung. Daher wird bei der Übersetzung häufig der Ansatz verfolgt, dass dasKonzept der abstrakten Objektwelt zunächst in eine funktionenbasierte, imperativeProgrammierung überführt wird, um anschließend die eigentlichen maschinennahenZielprogramme zu generieren.Diese Seminararbeit verfolgt das Ziel, zu Beginn das Konzept der ObjektorientiertenProgrammierung und dessen Besonderheiten vorzustellen, um im Anschluss daran aufdessen schematische Übersetzung einzugehen.Der Aufbau der Arbeit stellt sich wie folgt dar. Dem einleitenden Teil folgend wird inKapitel Zwei eine allgemeine Einordnung in Programmiersprachen vorgenommen. Diesumfasst eine Vorstellung des zentralen Konzeptes der Klassen, Objekte und Instanzen,der Einfach- und Mehrfachvererbung sowie des Polymorphismus. Im dritten Teil wirddie konkrete Übersetzung des Konzeptes vorgestellt, indem zunächstLaufzeitumgebungen am Beispiel der Java Virtual Machine und der Common LanguageRuntime thematisiert werden. Darauf folgt unter Einbezug der ProgrammiersprachenC++, C# und Java die schematische Übersetzung <strong>von</strong> Klassenstrukturen sowie <strong>von</strong>Einfach- und Mehrfachvererbungen. Ein besonderes Augenmerk wird dabei dem Themader Generizität gewidmet, indem zwei gegensätzliche Vorgehensweisen derÜbersetzung vorgestellt werden. Die Arbeit schließt mit einer kurzen Zusammenfassungund einem Fazit.1


Kapitel 2: Objektorientierte Programmiersprachen2 Objektorientierte Programmiersprachen2.1 EinordnungProgrammierungen erfolgen heute i.d.R. in höheren Programmiersprachen aus einerproblemorientierten Perspektive. Hier können vier wichtige Klassen <strong>von</strong>Programmiersprachen unterschieden werden [WS07, S. 1 f; ALSU08, S. 16 f].Funktionale <strong>Sprachen</strong> (pure Lisp, SML, Haskel) basieren auf dem Ausführungsprinzipder Reduktion. Für diese Klasse ist eine fehlende Trennung zwischen Anweisungen undAusdrücken und eine rekursiven Funktionenstruktur (Funktionen können Ergebnisse<strong>von</strong> Funktionen sein) charakteristisch. Die zweite Klasse, die logischenProgrammiersprachen (Prolog), basieren auf einer operationellen Sicht derPrädikatenlogik und dem Ausführungsmechanismus der Resolution, einem Verfahren,dass für das Beweisen <strong>von</strong> Implikationen in der Prädikatenlogik entwickelt wurde. DieKlasse der imperativen <strong>Sprachen</strong> (Algol 60, Fortran, Pascal, Ada, C) orientiert sich ander Struktur des <strong>von</strong>-Neumann-Rechners, der heute die Basis für sehr vielekommerzielle Rechner bildet.Die für diese Seminararbeit entscheidende Klasse der objektorientiertenProgrammiersprachen ist im Kern imperativ und unterstützt eine Datenabstraktion undeinen ganz neuen Ansatz der Softwareentwicklung.2.2 Klassen- und objektorientiertes Sprachkonzept2.2.1 Objekte und KlassenDie Objektorientierung ist ein altes Konzept der Informatik und basiert auf Objekten,(abstrakten) Klassen, Attributen und Operationen [Ze04, S. 3]. Eine zentrale Bedeutunghat dabei die Überlegung, wie ein betrachteter Gegenstandsbereich in der Realität inObjekten abgebildet werden kann und wie sich diese Objekte beschreiben undspezifizieren lassen.Ein Objekt besitzt dabei immer einen eindeutigen Zustand, ein wohldefiniertesVerhalten und ist anhand Merkmale eindeutig identifizierbar (Objektidentität). DasErzeugen eines Objektes erfolgt i.d.R. anhand des Schlüsselwortes new Objekt().Jedes Objekt ist daher immer nur Instanz einer konkreten Klasse, die die Funktionen2


Kapitel 2: Objektorientierte Programmiersprachenund Eigenschaften zusammenfasst und daher als Bauplan für das Objekt verstandenwerden kann.Die Eigenschaften <strong>von</strong> Klassen werden dabei Attribute genannt, mit denen genau einDatentyp und Wertebereich verbunden wird. Alle Objekte dieser Klasse besitzen dabeiformal die gleichen Attribute, jedoch pro Instanz eigenständige Ausprägungen. Nebenden Attributen werden ebenfalls innerhalb einer Klasse Methoden definiert, die zumAuslesen und Manipulieren <strong>von</strong> den Attributen einer Instanz verwendet werden können.Der Datenaustausch zwischen Objekten kann aufgrund dieser Kapselung nur mit Hilfe<strong>von</strong> Nachrichten erfolgen (Objektinstanz.Methode() oder Objektinstanz->Methode()), d.h. ein Objekt ruft die Methoden des anderen Objektes auf undverarbeitet einen möglichen Rückgabewert. Welche Methodenimplementierung bei demAufruf einer Methode gewählt wird, ist für das aufrufende Objekt irrelevant, da dieeigentlichen Implementierungen der Klassen <strong>von</strong> dem aufgerufenen Objekt gesteuertwerden und ohne Konsequenzen für das Gesamtsystem geändert werden können [HB98,S. 47].Das vorgestellte Klassen- und Objektkonzept ermöglicht eine Kapselung undGeheimhaltung <strong>von</strong> Daten und Zuständen sowie eine hohe Modularisierung undWiederverwendbarkeit der Programmierungen.2.2.2 VererbungskonzeptBei dem Konzept der Vererbung wird zwischen verschiedenen Klassen eine Hierarchiehergestellt. Dadurch ist es möglich, mit einer generalisierten Superklasse (auchBasisklasse oder Oberklasse genannt) eine Grundstruktur festzulegen und diese an eineUnterklasse (auch: abgeleitete Klasse) zu vererben. Alle Merkmale einer Oberklassewerden dabei an die Unterklasse weitergegeben, um diese im konkretenAnwendungsfall weiter zu spezialisieren [Ze04, S. 6]. Die Vorteile sind hier, dass dieWiederverwendbarkeit und die Erweiterbarkeit des Codes unterstützt wird und eingemeinsames Verhalten geteilt werden kann. Die Erweiterbarkeit wird dadurchermöglicht, dass Methoden in Unterklassen Implementierungen der Oberklasseüberschreiben können.Es kann zwischen einer Einfach- und Mehrfachvererbung unterschieden werden, die imNachfolgen erläutert werden [BH98, S. 29].3


Kapitel 2: Objektorientierte ProgrammiersprachenBei der Einfachvererbung erbt eine Klasse B alle Attribute und Methoden einer KlasseA. Dadurch sind alle Instanzen der Klasse B automatisch auch Instanzen der Klasse A,da B als Teiltyp <strong>von</strong> A verstanden werden kann. Im Beispiel in Abbildung 1 gibt es einegeneralisierte Klasse Mitarbeiter, die die beiden Unterklassen Angestellter und Arbeiterbeerbt. Gemeinsamkeiten können damit in der Oberklasse festgelegt werden, währendSpezialisierungen in den Unterklassen erfolgen, indem z.B. die Ueberweisen()Methoden überschrieben und eine LohnBerechnen() Methode neu implementiertwird.Abbildung 1: EinfachvererbungVon Mehrfachvererbung spricht man, wenn im Gegensatz zur Einfachvererbung eineKlasse <strong>von</strong> mindestens zwei Oberklassen erbt. Die Klassenhierarchie lässt sich indiesem Fall als ein gerichteter azyklischer Graph darstellen [BH98, S. 43 f]. MehrfacheVererbung kann <strong>von</strong> Vorteil sein, wenn komplexere Klassen elementare Fähigkeiten<strong>von</strong> kleinen Basisklassen erben sollen, wie z.B. die Basisklassen persistent oderqueueable, die Objekte im Dateisystem ablegen bzw. Objekte in Warteschlangenorganisieren. Mehrfache Vererbung ist damit ein sehr vielseitiges und mächtigesKonzept, benötigt jedoch einen stringenten Ansatz bei der Übersetzung, um möglicheKonflikte und Mehrdeutigkeiten aufzulösen (Vgl. Kapitel 3) [WH97, S. 189].Da die Mehrfachvererbung neben Vorteilen auch diverse Nachteile mit sich bringt, istbei vielen neuen Programmiersprachen keine Mehrfachvererbung vorgesehen. AlsErsatz für diese Einschränkung wurden Schnittstellen (auch: Interfaces) realisiert, dieeine besondere Form <strong>von</strong> Klassen darstellen [Ze04, S. 50]. Schnittstellen enthaltenausschließlich Konstanten und abstrakte Operationen, stellen selbst jedoch keineImplementierung zur Verfügung. Eine Klasse kann beliebig vielen Schnittstellen erben4


Kapitel 2: Objektorientierte Programmiersprachenbzw. implementieren, wodurch sichergestellt wird, das Methoden und Attribute beiInstanziierung einer Klasse in jedem Fall zur Verfügung stehen.Listing 1 enthält für die zwei sehr verbreiteten <strong>Sprachen</strong> Java und C#, die beide keineMehrfachvererbung unterstützen, den Syntax für die Verwendung <strong>von</strong> Interfaces.// Javaclass Klassenname implements [Interfaceliste] {...}// C#class Klassenname : [Interfaceliste] {...}Listing 1: Realisierung <strong>von</strong> Schnittstellen in Java und C#Aus den Vererbungshierarchien <strong>von</strong> typisierten objektorientierten <strong>Sprachen</strong> ergebensich drei aufeinander aufbauende Regeln, die elementare Fähigkeiten der Klassen undObjektinstanzen regeln und festlegen.Die erste Regel, die Teiltypregel besagt, dass bei Erwartung eines Objektes A (z.B. beieiner Zuweisung oder als Rückgabewert einer Methode) auch Objekte einer Unterklassezugewiesen bzw. zurückgegeben werden können [WM07, S. 178]. Jedes Objekt einerUnterklasse ist automatisch auch Element der Oberklasse. Auf das soeben eingeführteBeispiel bezogen bedeutet dies, dass einer Variable vom Typ Mitarbeiter auch einObjekt vom Typ Angestellter zugewiesen werden kann (Vgl. Listing 2).Mitarbeiter M = new Angestellter();Float Betrag = M.Ueberweisen(); // Angestellter::Ueberweisen();Listing 2: Teiltyp- und Methoden-Auswahl RegelAus dieser ersten Regel resultiert unmittelbar die Methoden-Auswahl-Regel. Diesebesagt, dass in einer Unterklasse B eine <strong>von</strong> A geerbte und neu implementierte Methodeauch dann aufgerufen werden muss, wenn B als Element <strong>von</strong> A benutzt wird. Auf dasBeispiel bezogen (Vgl. Listing 2 und Abbildung 1) muss die <strong>von</strong> der KlasseAngestellter neu implementierte Methode Ueberweisen() aufgerufen werden,obwohl das Objekt <strong>von</strong> einer Variable vom Typ Mitarbeiter aufgenommen wurde.Eine Nichtbeachtung dieser Regel könnte unerwartete Auswirkungen auf dieProgrammlogik haben, sofern die Angestellter::Ueberweisen()auf ganz andereDaten zurückgreift und die vererbte FunktionMitarbeiter::Ueberweisen()verwendet würde.Diese Methoden-Auswahl-Regel stellt den Übersetzer vor eine gewisseHerausforderung, da die richtige Methodenimplementierung zur Übersetzungszeit nochnicht feststeht und erst zur Laufzeit bestimmt werden kann. Dies impliziert5


Kapitel 2: Objektorientierte Programmiersprachenschlussendlich die letzte wichtige Regel. Die Dynamische Bindungs-Regel besagt, dassdie Auswahl der Methodenimplementierung zur Laufzeit an das Objekt gebundenwerden muss, wenn dessen Klassenzugehörigkeit zur Übersetzungszeit nicht bekannt ist[WB97, S. 179]. Dieser Vorgang wird auch als spätes Binden bezeichnet und bietet einezusätzliche Flexibilität bei der Programmentwicklung. Das Gegenteil hierzu ist dasfrühe oder statische Binden, bei dem der Übersetzer schon zur Übersetzungszeit dieMethoden feststellen und damit festlegen kann [BH98, S. 128].2.2.3 PolymorphismusObjektorientierte <strong>Sprachen</strong> stellen das Konzept der Polymorphismus zur Verfügung,dass als Vielgestaltigkeit übersetzt werden kann. Unter Polymorphismus versteht mandie Fähigkeit, dass der gleiche Methodenaufruf bzw. die gleiche Nachricht eineunterschiedliche Reaktion auslöst, da die gewählte Implementierung <strong>von</strong> Methodeninnerhalb <strong>von</strong> Klassenhierarchien <strong>von</strong> verschiedenen Faktoren abhängt. Dieses Konzepterfordert die bereits eingeführte Fähigkeit des späten bzw. dynamischen Binden, da erstzur Laufzeit entschieden werden kann, welche Methodenimplementierung genutztwerden wird.Polymorphismus kann anhand der nachfolgenden Abbildung charakterisiert und in dieBereiche Überladen, Subklassen-, parametrischer- und Inklusionspolymorphismusunterteilt werden [BH98, S. 53].PolymorphismusAd-hoc-P.universeller P.ÜberladenCoercionInklusionParametrischAbbildung 2: Übersicht PolymorphismusÜberladen bedeutet, wenn eine namensgleiche Methode mehrfach implementiert wirdund sich nur anhand der übergebenen Parameter (Signatur) unterscheidet. WelcheMethode aufgerufen wird, wird zur Laufzeit durch den Übersetzer entschieden, indemdie übergebenen Argumente ausgewertet werden. Das nachfolgende Beispiel zeigt dasÜberladen <strong>von</strong> Methoden anhand des bekannten Beispiels:6


Kapitel 2: Objektorientierte Programmiersprachenpublic class Angestellter extends Mitarbeiter {public class Ueberweisen(){ /*.*/ }public class Ueberweisen(float betrag){ /* */ }public class Ueberweisen(float betrag, bool Irgendwas){ /* */}}Listing 3: Überladen und ÜberschreibenCoercion bezeichnet die automatische und implizite Typumwandlung, um eineOperation durchführen zu können. Um die Addition <strong>von</strong> 3 + 5,4 durchführen zu können,erfolgt automatisch die Typumwandlung in 3,0 + 5,4.Beim Inklusions-Polymorphismus kann eine Methode mit mehreren Typen arbeiten,wenn diese Typen in einer Superklassen-Unterklassen Beziehung stehen. Diese Formdes Polymorphismus findet bei Vererbung ohne Re-Implementierung statt. EineEinschränkung auf bestimmte Typen schließt dabei typbedingte Laufzeitfehler aus.Anhand der bereits bekannten Klassenhierarchie kann hier die Struktur sehr gutverdeutlicht werden. Die mA und mB Objekte vom Typ Mitarbeiter können Instanzender Unterklassen Angestellter und Arbeiter aufnehmen. Der Inklusions-Polymorphismus ermöglicht den Umfang des bereits vorgestellten Vererbungskonzeptesund ist u.a. der Grund für den Bedarf der drei Regeln.public class SubklassenPolymorphismus {public static void main(String[] args){Mitarbeiter mA = new Angestellter();Mitarbeiter mB = new Arbeiter();}}Listing 4: Subklassen-PolymorphismusParameterpolymorphie ist die letzte Art des Polymorphismus, die auch für den weiterenVerlauf der Ausarbeitung <strong>von</strong> Bedeutung ist. Diese Art liegt vor, wenn eine MethodeParameter allgemeinen Typs akzeptiert (Generizität). Formal wird dies i.d.R. überPlatzhalter gelöst, die beim Aufruf mit dem benötigten Objekttyp ersetzt werden. DerVorteil dieser Platzhalter besteht darin, dass häufig benötigte Methoden wie Container,Listen und Bäume nur einmal implementiert werden müssen und für alle Datentypengenutzt werden können.public class Datenobjekt {private T daten;public Datenobjekt(T daten){ this.daten = daten; }public T getDaten(){ return daten; }public void setDaten(T daten){ this.daten = daten; }}Datenobjekt TestA = new Datenobjekt(“String“);7


Kapitel 2: Objektorientierte ProgrammiersprachenString s = TestA.getDaten();Datenobjekt TestB = new Datenobjekt(23);Listing 5: parametrische GenerizitätListing 5 zeigt am Beispiel <strong>von</strong> Java 1.5 eine Klasse und die Instanziierung anhandeiner expliziten Parametrisierung. Sofern keine konkreten Restriktionen gesetzt werden,können alle Datentypen aufgenommen werden [BH08, S. 49]. Es ist jedoch möglich,den Wertebereich anhand <strong>von</strong> Grenzen nach oben und unten zu beschränken. Java stellthier die beiden Schlüsselwörter extends und super zur Verfügung, die eine obere unduntere Grenze setzen können.In gewissem Rahmen kann Generizität auch mit Hilfe <strong>von</strong> Vererbung realisiert werden,da in einer Superklassen-Unterklassen Hierarchie jede Instanz einer Unterklasse auchder Superklasse zugewiesen werden kann. An diesem Ansatz ist jedoch problematisch,dass Laufzeitfehler auftreten können, da die Möglichkeit besteht, Datentypen zumischen (BH98, S. 52).8


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>3 Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>3.1 Reale und virtuelle MaschinenDie Zielsprache eines klassischen Compilers ist die Maschinensprache <strong>von</strong> einemkonkreten realen Rechnertyp, die in großer Vielfalt käuflich erworben werden können.Die Zielsprache der Übersetzung wird dadurch <strong>von</strong> dem real verwendeten Rechner,genauer noch, vom Prozessortyp, festgelegt.Die direkte Übersetzen des Programmiercodes in den <strong>von</strong> der realen Maschinebenötigten Code hat eine hohe Geschwindigkeit als Vorteil, jedoch auch Nachteile.Einerseits will man bei höheren Programmiersprachen einen Programmcode verwenden,der Befehle benötigt, die <strong>von</strong> realen Rechnern nicht zur Verfügung gestellt werden,andererseits muss der Übersetzer ständig an neue Rechnergenerationen angepasstwerden, da sich u.a. die Instruktionssätze der Rechnerarchitektur im Laufe der Zeitändern könnten [WS07, S. 4].Aus diesen Gründen verfolgt man bei höheren Programmiersprachen wie Java und C#die Strategie, einen idealisierten abstrakten Rechner als Zielsprache zu verwenden, umeine vollständige Plattformunabhängigkeit zu gewährleisten. Die virtuelle Maschine hat,wie jeder andere Rechner auch, eine Maschinenspezifikation, die Maschinenbefehle undzur Verfügung stehende Register und den Hauptspeicher festlegt [Da97, S. 27 f]. Dienachfolgende Grafik stellt die Bestandteile einer virtuellen Maschine am Beispiel derJava Virtual Machine schematisch dar.Abbildung 3: Aufbau Laufzeitumgebung am Beispiel der JVM [Mö06, S. 767]Vom Ablauf her wird der vom Programmierer erstellte Quellcode durch den Übersetzerin den sogenannten Bytecode übersetzt, der i.d.R. die meisten Befehle durch eineinziges Byte codiert [Mö06, S. 766]. Dieser Bytecode wird dann durch die virtuelleMaschine direkt interpretiert oder durch einen Just-in-Time-Compiler (JIT-Compiler) inden Code der realen Maschine übersetzt, auf der die virtuelle Maschine läuft.9


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>Neben der Plattformunabhängigkeit hat eine virtuelle Maschine noch eine weitereStärke, da sie als Betriebssystemerweiterung angesehen werden und damit Diensteanbieten kann, die in herkömmlichen Betriebssystemen fehlen. Dies sind u.a. eineautomatische Speicherbereinigung (Garbage Collection) und Sicherheitsmechanismenin Form <strong>von</strong> Zugriffsrechten auf Datei- und Netzwerkebene, sowie Code-Verifikation,die erstellten Bytecode auf mögliche Manipulationen durch Hacker überprüft [Mö06, S.766 f; MG00, S. 1]. Diese Unabhängigkeit hat in jedem Fall eine geringereAusführgeschwindigkeit zur Folge, wobei dies in Zeiten schneller werdenderRechnergeschwindigkeiten vertretbar sein dürfte.Die am weitverbreitetsten virtuellen Maschinen sind die Java Virtual Machine (JVM)<strong>von</strong> Sun und die Common Language Runtime (CLR) <strong>von</strong> Microsoft. BeideLaufzeitumgebungen basieren auf einer Stapelarchitektur [ALSU08, S. 621], d.h. alleOperanden werden auf einen Operandenstapel geladen, wo sie <strong>von</strong> Operatoren alsArgumente verwendet werden. Bei der JVM wird der vom Compiler erzeugte Bytecodeinterpretiert und nur sehr häufig aufgerufene Programmteile werden bei der JVM durchden JIT-Kompilierung „on demand“ in Maschinencode übersetzt. Die CLR übersetztbeim Laden den durch den Übersetzer erstellten Intermediate Language Code (IL-Code)nur bei Bedarf in den Maschinencode (Native Code), d.h. wenn ein Programmaufgerufen wird [LS08, S. 25 f]. Der JIT-Compiler (Jitter) geht dabei soweit, dass nichtverwendete Programmmodule erst bei Programmaufruf übersetzt werden.Abbildung 4: Ausführung eines Programmes [LS08 S. 30]Ein elementarer Unterschied zwischen JVM und CLR ist, dass der parametrischePolymorphismus (Vgl. Kapitel 2.2.3) bei der JVM auf Übersetzerebene und bei derCLR auf Ebene der Laufzeitumgebung realisiert wird. Dies hat maßgeblichen Einflussauf die konkrete Umsetzung diese Technik (Vgl. Kap. 3.4.2).Da Laufzeitumgebungen ein sehr umfangreiches Themengebiet sind, kann an dieserStelle nur eine kurze Einführung in das Grundprinzip erfolgen. Für eine abschließendeBetrachtung sei daher an dieser Stelle an die anderen Seminararbeiten bzw. an dieentsprechende Fachliteratur verwiesen [MG00].10


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>3.2 Übersetzung <strong>von</strong> MethodenWie bereits vorgestellt arbeiten, Methoden auf den Instanzen einer Klasse, wobei einAustausch über Nachrichten möglich ist. Bei dem Aufruf o.m(arg1, arg2) wird dieMethode m der Objektinstanz o aufgerufen und die zwei Argumente arg1 und arg2übergeben. Beim Übersetzen <strong>von</strong> Methoden wird der Ansatz verfolgt, die Methoden inimperative Funktionen ohne Objektorientierung zu überführen, ohne dabei den Kontext(this) zu verlieren. Listing 6 zeigt allgemein und als Beispiel für die obigenMethodenaufrufe, wie diese Transformation erfolgt [WM97, S. 183].MethodeFunktionDefinition objekt.methode() fmethode(objekt, )Beispiel o.m(arg1, arg2) fm(o, arg1, arg2)Listing 6: Transformation <strong>von</strong> Methoden in FunktionenDa aufgrund des möglichen Polymorphismus <strong>von</strong> Methoden eine Eindeutigkeit alleineüber Methodennamen nicht sichergestellt werden kann, wird in Java und C++ derFunktionsname nach dem Schema [M]__[#][K][D] gebildet. [M] steht dabei für denMethodenname, [K] für den Klassennamen, [#] für die Anzahl der Zeichen desKlassennamens und [D] für die Datentypen der übergebenen Argumente. DieÜbernahme der Datentypen ist erforderlich, da aufgrund des Überladens <strong>von</strong> Methodenein Methodenname innerhalb einer Klasse nicht eindeutig ist. Eindeutigkeit kann dahererst durch den Einbezug der Datentypen gewährleistet werden [BH98, S. 103 f].// Methode Ueberweisen(double betrag);// abgeleitete Funktion Ueberweisen__11MitarbeiterDoub(Klasse-Mitarbeiterthis, double betrag);Listing 7: Beispiel für die Transformation <strong>von</strong> Methoden in FunktionenIn Listing 7 wird am Beispiel der aus Kapitel 2 bekannten Klasse Mitarbeiter dieseTransformation in eine eindeutige, imperative Funktion vorgenommen. DieseVorgehensweise stellt sicher, dass die global gültigen Funktionsnamen in jedem Falleindeutig sind und Mehrdeutigkeiten aufgrund gleicher Methodennamen inunterschiedlichen Klassen vollständig ausgeschlossen werden können.Im Anschluss daran können die Funktionen mit Hilfe der Übersetzungstechniken <strong>von</strong>traditionellen Compilern übersetzt werden.11


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>3.3 Übersetzung <strong>von</strong> VererbungDie Vererbung ist eines der wichtigsten Konzepte der objektorientiertenProgrammierung, stellt jedoch gleichzeitig eine große Herausforderung für denCompiler dar. Grundsätzlich können bei der Implementierung <strong>von</strong> Vererbungsrelationenzwei Ansätze unterschieden werden. C++ (u.a. <strong>Sprachen</strong>) arbeiten mit der Kopier-Sicht,bei der eine erbende Klasse <strong>von</strong> der beerbten Klasse alle Methoden undInstanzvariablen erhält und auch selbst besitzt. Bei der Such-Sicht werden geerbteMethoden und Instanzvariablen nicht kopiert, sondern, wenn ein Zugriff in der aktuellenKlasseninstanz fehlschlägt, in den Oberklassen gesucht. Dieser Ansatz wird u.a. <strong>von</strong>Smalltalk-80 und Java verfolgt [BH98, S. 39].Nachfolgend wird primär C++ zur Veranschaulichung verwendet werden, da hier dieÜbersetzungstechniken am leichtesten verständlich gemacht werden können.3.3.1 EinfachvererbungBei der einfachen Vererbung kann jede Klasse nur <strong>von</strong> einer Oberklasse erben. Die sichdaraus ergebenden Vererbungshierarchien sind dabei Bäume bzw. Wälder. Beidynamischen Methoden, die wie in Kapitel 2.2.3 vorgestellt, überschrieben undüberladen werden können, besteht aufgrund des dynamischen Bindens dieHerausforderung darin, bei Laufzeit die passende Methode zu ermitteln und zu binden.Der Ansatz des Übersetzers besteht hierbei darin, pro Klasse eine Methodentabelle zuverwalten, die alle Methoden einer Klasse enthält, die möglicherweise dynamischgebunden werden müssen [WM97, S. 187]. In C++ enthält jedes Objekt einer Klasse alserstes einen Zeiger auf die zur Klasse gehörige Methodentabelle (virtual function table),wie in der Abbildung für das bereits bekannte Beispiel dargestellt.12


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>Abbildung 5: Klassen mit MethodentabellenDer Übersetzer bindet dabei Methodennamen an die Indizes innerhalb einerMethodentabelle und kann damit die dem Index zugeordnete Implementierung aufrufen.Eine Unterklasse erbt eine Kopie der Methodentabelle der Oberklasse, wobei für alle inder erbenden Klasse neu implementierten Methoden in der Methodentabelleentsprechend ein Verweis auf die neue Implementierung vorgenommen wird. An dasEnde dieser Methodentabelle werden erstmals implementierte Methoden angehängt,siehe z.B. Arbeiter::LohnBerechnen() aus dem Beispiel. Alle Arbeiter Objekte,die instanziiert werden, teilen sich dabei eine Methodentabelle, da diese für alleInstanzen gleich ist.Ein besonderes Augenmerk muss im Rahmen der Vererbung auf die verlinkteMethodentabelle gelegt werden. In Kapitel 2.2.2 wurde die Methoden-Auswahl-Regelvorgestellt, die an allen Stellen, wo ein Mitarbeiter-Objekt erwartet wird, auch einAngestellten- oder Arbeiter-Objekt zulässt. Sofern also einem Arbeiter-Objekt einerVariable vom Typ Mitarbeiter-Objekt zugewiesen wird, muss die Methodentabelle desArbeiter-Objektes <strong>von</strong> dem Mitarbeiter-Objekt geladen werden, da nur so die richtigeMethodenimplementierung ermittelt werden kann.Dieses Beispiel zeigt, dass für Vererbungsrelationen verschiedene sogenannte Sichtenauf ein Objekt definiert werden müssen bzw. die Möglichkeit bestehen muss, zwischenverschiedenen Sichten hin und her zu schalten [BH98, S. 107]. In diesem Fall erbt dieKlasse Arbeiter <strong>von</strong> der Klasse Mitarbeiter und kann so auch einem Objekt <strong>von</strong> TypMitarbeiter zugewiesen werden [BH98, S: 32]. Um jedoch die richtigeMethodenimplementierung wählen zu können, muss während der Laufzeit dieMethodentabelle der Arbeiter-Klasse vom Objekt der Klasse Mitarbeiter geladenwerden.3.3.2 MehrfachvererbungenBei der bisherigen einfachen Vererbung erbte immer eine Unterklasse <strong>von</strong> maximaleiner Oberklasse. Von Mehrfachvererbung spricht man dann, wenn eine Klasse <strong>von</strong>mindestens zwei Oberklassen erbt und die daraus resultierende Klassenhierarchiekeinen Baum, sondern einen gerichtete azyklische Graphen ergibt. Diese fehlendeeindeutige Klassen-Wurzel führt zu verschiedenen Problemen, wie z.B. zuMehrdeutigkeiten bei der Benennungen <strong>von</strong> Methoden und Attributen. Fragestellungen13


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>sind zum einen, auf welche Methoden bzw. Attribute zugegriffen werden soll, wennzwei vererbende Klassen diese Methoden bzw. dieses Attribut jeweils implementierthaben. Zum anderen auch, wie bei einer wiederholten Beerbung verfahren werden soll,wenn zwei Klassen B 1 und B 2 <strong>von</strong> einer Hauptklasse A erben und eine dritte Klasse Cjeweils die zwei vorgenannten Klassen B 1 und B 2 beerbt [WH97, S. 190]?Abbildung 6: Mehrfachvererbung und daraus resultierende NamenskonflikteMehrdeutigkeiten können unterschiedlich aufgelöst werden. Eine Regelung ist, denvererbenden Klassen unterschiedliche Prioritäten zuzuweisen. Sobald ein Konfliktauftritt, kann der Wert bzw. die Implementierung der Klasse mit der höchsten Prioritätgewählt werden. Der Nachteil dieses Ansatzes ist allerdings, dass Widersprüche für denEntwickler nicht immer offensichtlich bzw. erkenntlich sein müssen, wodurchmöglicherweise Implementierungen gewählt werden, die vom Entwickler eigentlichnicht vorgesehen waren [WH97, S. 190]. In C++ wird das Problem so gelöst, dass das:: Konstrukt zur Verfügung gestellt wird, das einen direkten und expliziten Zugriff aufdie gewünschte Implementierung bietet. Im Beispiel auf der obigen Abbildung könnendie jeweiligen Implementierungen <strong>von</strong> der Methode bar() <strong>von</strong> B1 und B2 alsB1::bar() bzw. B2::bar() angesprochen werden [BH98, S. 44].Abbildung 7: Einfache- und Mehrfachinstanziierung [BH98, S. 45]Das Problem der wiederholten Beerbung kann mit zwei entgegensetzen Ansätzen gelöstwerden, indem das Erbe mehrfach oder ein einziges Mal instanziiert wird. Beide14


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>Ansätze haben je nach vorliegendem Fall ihre Existenzberechtigung. Bei dem Ansatzder Mehrfachinstanziierung ergeben sich zwei A-Teilobjekte (siehe Abbildung 7) ineinem C-Objekt und daraus resultierend auch zwei A-Sichten auf ein C-Objekt [BH98,S. 45]. Eine ausführliche Betrachtung <strong>von</strong> zwei konkreten Beispielen, wann eineEinfach- bzw. eine Mehrfachinstanziierung sinnvoll ist, liefert die Fachliteratur [WH97,S. 192] und kann aus Platzgründen an dieser Stelle nicht erfolgen.Bei der Übersetzung <strong>von</strong> Mehrfachvererbungen, die unabhängig <strong>von</strong>einander sind, undkeine namentlichen Überschneidungen haben, muss folgendes Problem überwundenwerden. Wie bereits vorgestellt, wird in C++ mit Methodentabellen gearbeitet, die einenVerweis auf die zu nutzende Methodenimplementierung enthalten. Bei einerEinfachvererbung wird die Methodentabelle der vererbenden Klasse in die erbendeKlasse übernommen und entsprechend angepasst. Dies ist hier jedoch nicht ohneweiteres möglich, da mehrere Methodentabellen vererbt werden, die entsprechendverarbeitet werden müssen.Ein Ansatz zur Lösung ist, die Methodentabelle für jede vererbende Klasse komplett inKopie zu erstellen um die entsprechenden Sichten erstellen zu können wenn z.B. ein CObjekt in einer Variable vom Typ B1 gespeichert wurde. Dies hat jedoch den Nachteil,dass der Speicherbedarf für die Ablage <strong>von</strong> den Methodentabellen exponentiell mit derKomplexität der Definition <strong>von</strong> C wächst und somit ungeeignet ist.-d1+foo()+bar()B1-d2+bar()B2DB1B2B1 + CMethodenB2 MethodenCMethodentabelle-d2+bar()CCAbbildung 8: Klassenhierarchie und Objektstruktur inkl. MethodentabellenAus diesem Grund wird mit einer verteilten Methodentabelle C gearbeitet. Die ersteMethodentabelle für B1 und C enthält dabei neben dem Zeiger auf dieMethodenimplementierung auch einen Offset ∆D, der einen Sprung zumentsprechenden Zeiger auf die B2 Methodentabelle enthält. Dadurch ist es jederzeitmöglich, zwischen den verschiedenen verlinkten Methodentabellen hin-/her zuspringen, um die korrekten Sichten zu bilden. Dieser Offset kann auch als eine15


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>Verschiebung verstanden werden, da die ursprünglich bei null startendeMethodentabelle <strong>von</strong> B2 um die Anzahl der B1+C Methodentabelle verschoben wird[WM97, S. 193; BH98, S. 110].Sehr viel aufwändiger wird die Übersetzung, wenn das Diamantproblem besteht, d.h.wenn wie in Abbildung 6 dargestellt, eine abhängige mehrfache Vererbung besteht unddie Methoden <strong>von</strong> A nur einfach instanziiert in C eingeht. In diesem Fall muss dieMethodentabelle neu generiert werden, da die Methodentabellen <strong>von</strong> B1 und B2aufgrund der einfachen Instanziierung ungeeignet sind, da sich B1 und B2 eine Instanzteilen, und nicht, wie in den eigenen Methodentabellen vermerkt, jeweils eine eigeneInstanz haben. Dies erfordert, analog zu den Methodentabellen, Indextabellen zugenerieren, die Offsets für die jeweils gültigen Kontexte enthalten. Eine weitereVertiefung dieser Übersetzung kann aus Platzgründen an dieser Stelle nicht erfolgenund kann in der entsprechenden Fachliteratur nachgelesen werden [WM97, S. 200-210].Um die vorgestellten Probleme zu umgehen, wird in vielen Programmiersprachen, u.a.bei Java und C#, auf echte Mehrfachvererbung verzichtet und als Ersatz hierfür dieImplementierung <strong>von</strong> Schnittstellen ermöglicht (Vgl. Kapitel 2.2.2). Dieser Ansatzschließt Mehrdeutigkeiten und Namensprobleme aus, erfordert bei der Übersetzungjedoch auch die Überwindung einer Schwierigkeit. Sofern die Klasse A und B einMethode M des Interfaces I implementieren, kann nicht garantiert werden, dass dieseMethode in den beiden Klasse A und B die gleiche Relativadresse hat. Die Lösung ist,je Klasse, die ein Interface implementiert, eine Hash-Tabelle h H zu pflegen, die diegültige Codeadressen für die durch A implementierten Methoden des Interfaces Ispeichert [WS07, S. 175 f]. In Java werden verschiedene Ansätze für dieImplementierung <strong>von</strong> Interfaces verfolgt, u.a. Searched ITables, Directly Index ITablesund interface method tables (IMT). Eine ausführliche Vorstellung der Ansätze kannunter [ACFG01] nachgelesen werden.3.4 Übersetzung <strong>von</strong> ParametrisierungIn Kapitel 2.2.3 wurde bereits das Konzept der Parametrisierung vorgestellt, das dazudient, Operationen zu definieren, die auf verschiedenen Datentypen arbeiten können.Obwohl streng typisierte <strong>Sprachen</strong> mit einer Typprüfung bereits durch den Übersetzereinen Sicherheits- und Effizienzvorteil haben, hat diese dynamische Typprüfung auch16


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>Vorteile, da ein und derselbe Algorithmus nicht für jeden Datentyp implementiertwerden muss.In den verschiedenen Programmiersprachen gibt es zwei unterschiedlicheÜbersetzungsvarianten für Parametrisierung. Einerseits die heterogene, bzw. homogeneKopiervariante [OW97, S. 2] und andererseits die echte generische Variante [BH98, S.112].3.4.1 KopiervarianteBei der heterogenen Kopiervariante wird die generische Definition als Muster mitPlatzhalter für den Datentyp verstanden. Bei Bedarf, d.h. bei Instanziierung, erfolgt ingewisser Weise eine Spezialisierung des Musters, in dem dieses expandiert wird[WH97, S. 215]. Der Platzhalter wird dabei vom Übersetzer durch den richtigenDatentyp ersetzt und die Klassendefinition angelegt. Letztendlich nimmt hierbei derÜbersetzter dem Programmierer die eintönige Arbeit ab, mit Hilfe <strong>von</strong> Copy & Paste,die verschiedenen Implementierungen zu erzeugen und insbesondere auf die korrekteBenennung der Funktions- und Klassennamen zu achten. Dieser Ansatz findet u.a. beiC++ mit Hilfe <strong>von</strong> templates Verwendung und ermöglicht eine Parametrisierung <strong>von</strong>Klassen und Funktionen [WH97, S. 213]. Listing 8 zeigt ein Beispiel für die templatesFunktion <strong>von</strong> C++.// Templatetemplate void vertausche(T &v1, T &v2){T h;..h = v1; v1 = v2; v2 = h;}// Erzeugte Kopien bei der Übersetzungvoid vertausche(int &v1, int &v2){int h;h = v1; v1 = v2; v2 = h;}void vertausche(string &v1, string &v2){string h;h = v1; v1 = v2; v2 = h;}Listing 8: Heterogene Übersetzung [BH98, S. 113]Der Vorteil dieser Vorgehensweise liegt darin, dass für jeden Datentyp eine auf denDatentyp optimierte Kopie des Programmcodes angelegt wird, der sehr schnellausgeführt werden kann. Daraus resultiert letztendlich jedoch der Nachteil dieses17


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>Ansatzes in Form eines hohen Speicherplatzbedarfes, der auch als Code Bloatbezeichnet wird [BH98, S. 115]. Realisierbar ist dieser Ansatz aufgrund des bereitsvorgestellten Konzeptes der Überladung (Vgl. Kapitel 2.2.3), bei der verschiedeneFunktionen den gleichen Namen haben und sich nur aufgrund ihrer Signatur (sieheListing 8) <strong>von</strong>einander unterscheiden.Der zweite Ansatz ist die homogenen Kopiervariante, die u.a. in Java zum Einsatzkommt. Da Generizität in Java ursprünglich nicht vorgesehen war, wurde dieUnterstützung erst ab Version 1.5 nachträglich in die Sprache integriert. Daher war dieunbedingte Designanforderung bei dieser Implementierung, dass eineAbwärtskompatibilität zu früheren Versionen gewährleistet und die Java VirtualMachine nicht verändert wird. Bei der homogenen Kopiervariante wird der Umstandausgenutzt, dass jede Typklasse automatisch die Klasse Object erbt, und somit Objectals gemeinsamer Nenner für alle Typen verwendet werden darf. Für jede parametrisierteKlasse (z.B. vertausche) wird daher nur genau eine Klasse erzeugt, die diegenerischen Typinformationen löscht (type erasure) und die Typparameter durch dieKlasse Object ersetzt [Br04, S. 12]. Da die im Programm instanziierten Klassen einenbestimmten Datentyp voraussetzen, muss bei Attributzugriffen sowieMethodenrückgaben eine explizite Typkonvertierung durchgeführt werden, umLaufzeitfehler zu verhindern.// Klasse zur Aufnahme <strong>von</strong> genau einem Objektpublic class Box {private T contents;..public box(T cont){ contents = cont; }..public T getContents(){ return contents; }public void setContent(T o){ contents = o; }}// Instanziierungpublic static void main(String[] args){Box b1 = new Box(“Meine Box”);String s = b.getContents();Box b2 = new Box(new Integer(3));Int i = b2.getContents();}// Homogene Übersetzungpublic class Box {private Object contents;..public box(Object cont){ contents = cont; }..public Object getContents(){ return contents; }public void setContent(Object o){ contents = o; }}18


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>// Übersetzung durch den Kompiler inkl. eingefügter Castspublic static void main(Object args){Box b1 = new Box((Object)“Meine Box”);String s = (String)b.getContents();Box b2 = new Box((Object)new Integer(3));Int i = (Integer)b2.getContents();}Listing 9: Homogene ÜbersetzungListing 9 zeigt exemplarisch eine homogene Übersetzung, bei der der Compiler zuallererst Datentypen in der Klasse Box durch den allgemeinen Datentyp Object ersetztund beim Instanziieren automatische Casts beim Übergeben und Zurückgeben <strong>von</strong>Objekten einfügt. Der Nachteil dieser Casts ist, das während der Ausführung keineInformationen zu Klassennamen, z.B. anhand des instanceof Operators, zur Verfügungstehen, da diese aufgrund der Type Erasure nicht vorhanden sind [ACS02, S. 2].Zusammenfassend kann gesagt werden, dass bei der heterogenen Variante eineSpezialisierung vorgenommen wird und bei der homogenen Übersetzung eineVerallgemeinerung erfolgt [OW97, S. 1].3.4.2 Echte generische VarianteDie echte generische Variante, die bei C# zum Einsatz kommt, verfolgt einengegensätzlichen Ansatz. Im Vergleich zu Java wurde bei der Einführung <strong>von</strong>Generizität die Common Language Runtime (Vgl. Kapitel 3.1) verändert und umgenerische Typen erweitert. Ein Nachteil der echten generischen Variante ist, dass neuegenerische Klassen in den .NET-Libraries nicht rückwärtskompatibel zu ihren nichtgenerischen Varianten sind, wobei die nachfolgenden Vorteile dieser konsequentenVorgehensweise sicher überwiegen dürften.Bei der Einführung <strong>von</strong> generischen Typen direkt in die Common IntermediateLanguage wurden umfangreiche Änderungen am JIT-Compiler, dem Compiler selbstsowie an Typloadern und Metadaten vorgenommen. Daraus ergeben sich viele neueMöglichkeiten in Bezug auf eine effiziente Umsetzung. Die Common LanguageRuntime verwendet dabei eine Mischung aus homogener und heterogener Übersetzung.Die Instanziierungen generischer Konstrukte erfolgen bei Bedarf zur Laufzeit durch denJIT Kompiler. Durch diese Lazy Specialization wird Zeit und Speicherplatz gespart, daausgeschlossen werden kann, dass Zielcode generiert wird, der letztendlich nichtausgeführt werden wird.19


Kapitel 3: Übersetzung <strong>von</strong> objektorientierten <strong>Sprachen</strong>Wenn möglich wird dabei bereits kompilierter Code zwischen verschiedenen Instanzengeteilt und wiederverwendet [KS01, S. 7]. Wenn zur Laufzeit eine parametrischeMethode instanziiert werden soll, wird geprüft, ob auf bereits erzeugten Codezurückgegriffen werden kann. Eine Wiederverwendung ist ausschließlich dann möglich,wenn die übergebenen Datentypen zueinander kompatibel sind. Pauschal kann als Regeldefiniert werden, dass primitive Datentypen eine spezialisierte, heterogene Version derProgrammierung benötigen, während referenzierte Typen einen Code teilen können[YKS04, S. 45].Jede Instanz eines Objektes führt zur Laufzeit sämtliche Informationen zum eigenenDatentyp mit sich, da alle generischen Informationen während der Ausführung erhaltenbleiben [KS01, S. 11]. Gespeichert wird die Information über den aktuellen Zustandeiner Instanz in einer Methodentabelle (Vgl. Kapitel 3.3.1), wobei es dafür notwendigist, je Instanz eine Methodentabelle separat zu speichern [KS01, S. 8]. Dies hat denVorteil, dass Probleme im Zusammenhang mit Type Erasure vermieden werden undzeitintensive Casts bzw. Boxing/Unboxing Prozesse entfallen bzw. nur in Einzelfällenerforderlich sind [YKS04, S. 50].Alle während der Laufzeit relevanten Informationen zu Methoden und Typen werden ineffizient verwalteten Dictionaries vorgehalten, wobei diese wie <strong>von</strong> der Spezialisierungbereits bekannt, auch erst bei Bedarf (Lazy dictionary creation) erstellt undvervollständigt werden. Dies spart gegenüber dem Ansatz, ein initales Dictionary zuerstellen, erneut Zeit und Speicherplatz [KS01, S. 9].Eine umfangreiche Einführung in die Implementierung <strong>von</strong> Generizität in das .NETFramework liefern zwei Ausarbeitungen <strong>von</strong> Microsoft [YKS04; KS01].20


Kapitel 4: Zusammenfassung4 ZusammenfassungDie vorliegende Arbeit hat in die Grundlagen der Übersetzung <strong>von</strong> objektorientiertenProgrammiersprachen eingeführt und einen Überblick über die einzelnen Themenfeldervermittelt. In Kapitel Zwei wurde zunächst das grundlegende Konzept derObjektorientierung vorgestellt, sowie auf die Einfach- und Mehrfachvererbungeingegangen. Dabei wurden zudem die drei zentralen Regeln vorgestellt, die dasVerhalten zwischen Ober- und Unterklassen in Vererbungshierarchien regeln. ImAnschluss daran wurde ein Überblick über die verschiedenen Arten desPolymorphismus gegeben.In Kapitel Drei folgte die Thematisierung der Übersetzungstechniken, die entwickeltwurden, um die originären Techniken der objektorientierten Programmiersprachen zuübersetzen. Aus Platzgründen konnten viele Techniken nur vom Grundprinzip hererläutert werden, da jede Programmiersprache letztendlich bei der konkretenUmsetzung im Detail auf eigene effiziente Implementierungen zurückgreift.Vor- und Wegbereiter im Bereich der Laufzeitumgebungen war in jedem Fall Sun mitder Java Virtual Machine, die eine weite Verbreitung <strong>von</strong> Java über Plattformgrenzenhinweg ermöglicht hat. Während Sun jedoch bei neuen Versionen dieAbwärtskompatibilität immer als oberstes Ziel verfolgte, hat Microsoft mit derCommon Language Runtime auf Abwärtskompatibilität verzichtet und Neuerungeninsbesondere im Bereich der Generizität tief in die Laufzeitumgebung selbst integriert.Es hat sich insgesamt gezeigt, dass die Grundkonzepte der Übersetzung in diesemBereich bereits seit vielen Jahrzehnten bestehen, jedoch noch vieleOptimierungspotentiale im Bereich der Übersetzer (Vgl. Umsetzung <strong>von</strong> MethodenundInterfacetabellen) und der Laufzeitumgebungen bestehen.Insbesondere im Bereich der Programmiersprachen Java und C# und dendarunterliegenden Laufzeitumgebungen ist viel in Bewegung und Entwicklung. DieVeröffentlichung des .NET 4.0 Frameworks und damit auch <strong>von</strong> C# 4.0 wurde für denSommer/Herbst 2010 angekündigt, das viele neue Funktionen im Zusammenhang mitGenerizität sowie der parallelen Ausführung bietet.21


5 Literaturverzeichnis[ACFG01] Bowen Alpern, Antohny Cocchi, Stephen Fink, David Grove: Efficientimplementation of java interfaces: Invokeinterface considered harmless.SIGPLAN Not. 36(11) (2001) 108–124, URL:http://www.research.ibm.com/people/d/dgrove/papers/oopsla01.pdf.[ACS02]Eric Allen, Robert Cartwright, Brian Stoler: Efficient Implementation ofRun-time Generic Types for Java, IFIP WG2.1 Working Conference onGeneric Programming, 2002, 207 - 236.[ALSU08] Alfred V. Aho, Monica S. Lam, Ravi Sethi, Jeffrey D. Ullman: Compiler –Prinzipien, Techniken und Werkzeuge, Pearson Studium, 2008.[BH98] Bernard Bauer, Riitta Höllerer: Übersetzung objektorientierterProgrammiersprachen – Konzepte, abstrakte Maschinen und Praktikum„Java-Compiler“, Springer, 1998.[Br04][Da97][KS01]Gilad Bracha: Generics in the Java Programming Language, 2004, Url:http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf, Abrufdatum:25.04.2009.Matthias Kalle Dalheimer: Java Virtual Machine: Sprache, Konzept,Architektur, O´Reilly Verlag, 1997.Andrew Kennedy, Don Syme: Design and Implementation of Generics forthe .NET Common Language Runtime. In: Proceedings PLDI’01, 2001. Not.36, 5 (May. 2001), 1-12.[LS08] Dirk Louis, Shinja Strasser: Visual C# 2008, Markt+Technik Verlag, 2008.[Mö06][MG00][OW97][WS07][WM97][YKS04]H. Mössenböck: Systemsoftware. In: Informatik Handbuch. Hrsg.: PeterRechenberg, Gustav Pomberg. Hanser Verlag. 2006, S. 753-768.Erik Meijer, John Gough: Technical Overview of the Common LanguageRuntime, Url: http://research.microsoft.com/enus/um/people/emeijer/Papers/CLR.pdf,Abrufdatum: 30.04.2009.Martin Odersky, Philip Wadler: Pizza into Java: Translating theory intopractice, 24th ACM Symposium on Principles of Programming Languages,1997.Reinhard Wilhelm, Helmut Seidl: Übersetzerbau – Virtuelle Maschinen,Springer, 2007.Reinhard Wilhelm, Dieter Maurer: Übersetzerbau – Theorie, Konstruktion,Generierung, Springer, 1997.Dachuan Yu, Andrew Kennedy, Don Syme: Formalization of Generics forthe .NET Common Language Runtime, SIGPLAN Not. 39, 1 (Jan. 2004),39-51., URL: http://doi.acm.org/10.1145/982962.964005.


[Ze04]Klaus Zeppenfeld: Objektorientierte Programmiersprachen – Einführungund Vergleich <strong>von</strong> Java, C++, C#, Ruby, Spektrum Akademischer Verlag,2004.

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

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!