06.11.2013 Aufrufe

Dynamische Programmiersprachen - Fachgebiet ...

Dynamische Programmiersprachen - Fachgebiet ...

Dynamische Programmiersprachen - Fachgebiet ...

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>Dynamische</strong> <strong>Programmiersprachen</strong><br />

Von Lisp und Smalltalk zu Perl, Python, Ruby, Groovy …<br />

Seminar im WS 2008/2009<br />

Prof. Dr.-Ing. Hans-Jürgen Hoffmann<br />

TU Darmstadt, Fachbereich Informatik,<br />

FG <strong>Programmiersprachen</strong> und Übersetzer<br />

Seminarausarbeitung<br />

von<br />

<br />

<br />

<br />


INHALTSVERZEICHNIS 1<br />

Inhaltsverzeichnis<br />

1 Einleitung 2<br />

2 Was versteht man unter Binden ? 3<br />

2.1 Neu-Binden und Mutation . . . . . . . . . . . . . . . . . . . . . . . . 6<br />

2.2 Zeitpunkt des Bindens . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />

3 <strong>Dynamische</strong> Typisierung / Statische Typisierung 8<br />

3.1 Duck-Typing und die halbdynamische Sprache Boo . . . . . . . . . . . 10<br />

3.2 Vor- und Nachteile bei dynamischer / statischer Typisierung . . . . . . 12<br />

4 Polymorphe Variablen 13<br />

5 <strong>Dynamische</strong>- / Statische-Bindung 14<br />

5.1 Unterschiede zwischen dynamischer und statischer Bindung . . . . . . 18<br />

6 Fazit 19<br />

INHALTSVERZEICHNIS


1 EINLEITUNG 2<br />

1 Einleitung<br />

Das Wort Binden“ (engl. binding) besitzt eine Vielzahl von Bedeutungen und wird in<br />

”<br />

unterschiedlichem Kontext verwendet. So bezeichnet es so unterschiedliche Vorgänge<br />

wie beispielsweise das Zusammenfügen einzelner Seiten zu einem Buch, in der Chemie<br />

das Eingehen einer chemischen Verbindung und vieles mehr. Allgemein bezeichnet Binden<br />

das Herstellen einer Verbindung zwischen zwei oder mehreren Entitäten. In dieser<br />

Seminararbeit geht es um den Begriff Binden im Kontext der Informatik, insbesondere<br />

in Hinblick auf dessen Verwendung bei den <strong>Programmiersprachen</strong>.<br />

Diese Seminararbeit ist wie folgt gegliedert:<br />

Nach einer kurzen Einleitung im 1. Abschnitt wird in Abschnitt 2 versucht, eine kurze<br />

Definition des Begriffs Binden im Kontext der Informatik zu geben und die unterschiedlichen<br />

Bindungsarten vorzustellen.<br />

Der darauffolgende Abschnitt 3 befaßt sich mit den Unterschieden zwischen dynamischerund<br />

statischer Typisierung und dient als Grundlage für das Verständnis der unterschiedlichen<br />

Realisierungsmöglichkeiten für spätes Binden.<br />

Im 4. Abschnitt wird die Verwendung von polymorphen Variablen dargestellt und deren<br />

Zusammenhang mit spätem Binden aufgezeigt.<br />

Abschnitt 5 beschäftigt sich mit dem Zeitpunkt des Bindens und versucht den Unterschied<br />

zwischen frühem und spätem Binden zu verdeutlichen.<br />

Der sich anschließende letzte Abschnitt beinhaltet ein kurzes Fazit.<br />

Grundsätzliche wurde versucht, in jedem dieser Abschnitte die zu vermittelnde und<br />

notwendige Theorie durch möglichst viele Beispiele zu erläutern.


2 WAS VERSTEHT MAN UNTER BINDEN ? 3<br />

2 Was versteht man unter Binden ?<br />

Wie bereits in der Einleitung erklärt wurde, hat das Wort Binden je nach Zusammenhang<br />

eine unterschiedliche Bedeutung. Auch in der Informatik gibt es je nach Kontext<br />

unterschiedliche Definitionen was durch Begriffe wie beispielsweise Namensbindung,<br />

Variablenbindung und Funktionsbindung ausgedrückt wird.<br />

Eine allgemeine Definition für den Begriff Binden“ im Kontext der Informatik kann<br />

”<br />

man beispielsweise in der Wikipedia (siehe [1]) finden: In computer science, binding<br />

”<br />

is the creation of a simple reference to something that is larger and more complicated<br />

and used frequently.“ (In der Informatik bezeichnet der Begriff Binden“ die Erzeugung<br />

”<br />

einer einfachen Referenz zu etwas das größer und komplizierter ist und häufiger benutzt<br />

wird.)<br />

Ein Beispiel hierfür ist das folgende Python-Programm:<br />

Abbildung 1: Beispiel: Binden in Python<br />

In der ersten Zeile des Programms wird eine Funktion mit dem Namen meineFunktion“<br />

”<br />

definiert, die aus 1 Millionen Zeilen Code bestehen soll. Die Python-Anweisung def<br />

gefolgt von dem Namen der Funktion bewirkt, daß der nachfolgende Code (die 1<br />

Millionen Zeilen) mit dem Funktionsnamen assoziert werden, d.h. an diesen gebunden<br />

werden sollen. Der Funktionsname ist damit die einfache Referenz für diese 1 Millionen<br />

Zeilen Code, die ungleich größer und komplizierter sind. Nachdem der Code an den<br />

Funktionsnamen, d.h. an die Referenz dieser Funktion, gebunden wurde, reicht es aus,<br />

wenn man im Hauptprogramm nur noch diesen Funktionsnamen schreibt. Durch das<br />

Schreiben von einer Zeile Code werden 1 Millionen Zeilen Code ausgeführt.<br />

Grundsätzlich bezeichnet der Begriff Binden das Assoziieren von symbolischen Datenreferenzen<br />

mit physikalischen Maschinen-Adressen, d.h. ein symbolischer Bezeichner


2 WAS VERSTEHT MAN UNTER BINDEN ? 4<br />

ist eine Referenz auf eine physikalische Speicheradresse. Binden bezeichnet also das<br />

Verknüpfen eines Namens (Variablenname, Methodenname usw.) mit einer physikalischen<br />

Speicheradresse, d.h. dem Ansprechen von Speicheradressen mit einem Namen.<br />

Dies funktioniert daher auch nicht auf der Ebene der Maschinensprache, da dort keine<br />

Bezeichner mehr vorhanden sind, sondern nur noch die einzelnen Daten in ihrer<br />

Binärdarstellung im Speicher des Rechners vorliegen.<br />

Da in einer Speicheradresse eines Rechners verschiedene Daten, wie beispielsweise Variablen<br />

/ Attribute, Funktion / Methoden usw. abgelegt sein können, kann man auch<br />

all diese an einen symbolischen Namen innerhalb der Programmiersprache, so fern diese<br />

es zulässt, binden.<br />

Ein Beispiel für Funktionsbindung, also das Binden der Speicheradresse an der sich<br />

eine Funktion befindet an eine Variable, ist das untenstehende C-Programm:<br />

Abbildung 2: Beispiel: Funktionsbindung in der Programmiersprache C<br />

In dem obigen Programm werden in den ersten Zeilen zwei Funktionen f1 und f2<br />

definiert, die jeweils den gleichen Rückgabetyp, nämlich int besitzen und die lokale<br />

Integer-Variable x als Übergabeparameter erwarten. Anschließend wird im Hauptprogramm,<br />

das mit der Definition der main-Funktion beginnt, zuerst zwei Integer-Variablen


2 WAS VERSTEHT MAN UNTER BINDEN ? 5<br />

auswahl und x deklariert, wobei die erste die Auswahl des Benutzers im späteren Programmverlauf<br />

speichern und die zweite als Zählervariable innerhalb einer Schleife, die<br />

zur Ausgabe der berechneten Werte auf dem Bildschirm dient, benutzt werden soll.<br />

Danach erfolgt die Deklaration einer besonderen Art von Variablen, eines sogenannten<br />

Funktionszeigers (engl. function pointer).<br />

Ein Funktionszeiger ist eine Variable, in der die Adresse einer Funktion, die sich im<br />

Speicher eines Computers befindet, abgelegt werden kann. Über diese Zeiger-Variable<br />

kann die von ihr referenzierte Funktion im weiteren Verlauf eines Programmes einfach<br />

durch Schreiben des Funktionszeigernamens, d.h. äquivalent zu einem normalen<br />

Funktionsaufruf, aufgerufen werden. Der Funktionszeiger ist also eine Referenz auf eine<br />

Funktion, äquivalent zum Namen der Funktion, jedoch mit dem Unterschied, daß die<br />

Bindung nicht statisch ist, sondern durch Veränderung des Wertes des Funktionszeigers<br />

auf eine andere Speicheradresse während der Laufzeit geändert werden und damit<br />

an eine andere Funktion gebunden werden kann. Funktionszeiger ermöglichen damit<br />

dynamische Bindung an Funktionen.<br />

Im weiteren nicht dargestellten Verlauf des Programms, was durch die drei Punkte<br />

repräsentiert werden soll, wird der Benutzer in einem Menu dazu aufgefordert, entweder<br />

die erste oder die zweite Funktion auszuwählen, von der anschließend eine Wertetablle<br />

im Bereich von 0 bis 10 ausgegeben werden soll. Die Auswahl des Benutzers wird in<br />

der Variable auswahl gespeichert und in der anschließenden if-Bedingung ausgewertet.<br />

Je nachdem ob der Benutzer zuvor die erste oder die zweite Funktion ausgewählt hat,<br />

also abhängig vom Wert der Variablen auswahl wird dem Funktionszeiger func die<br />

Adresse der ersten Funktion f1 oder der zweiten Funktion f2 zugewiesen. Durch diese<br />

Zuweisung wird der Funktionszeiger an die Funktion f1 oder f2 gebunden. Danach kann<br />

durch einfaches Schreiben seines Namens, abhängig von dessen Inhalt, die Funktion<br />

f1 oder f2 aufgerufen werden, was in der nachfolgenden Schleife erfolgt. Innerhalb<br />

der Schleife wird zusätzlich die Schleifenzählvariable x als Parameter der durch den<br />

Funktionszeiger referenzierten Funktion übergeben und anschließend der Rückgabewert<br />

auf dem Bildschirm ausgegeben.<br />

Der gleiche Mechanismus findet sich auch in objektorientierten <strong>Programmiersprachen</strong>,<br />

beispielsweise in C#, als Methodenzeiger (engl. delegate) oder bei Objective-C in Form<br />

von Selektoren wieder.


2 WAS VERSTEHT MAN UNTER BINDEN ? 6<br />

2.1 Neu-Binden und Mutation<br />

Zwei weitere Begriffe, die häufig im Zusammenhang mit dem Begriff Binden verwendet<br />

werden, sind zum Einen das Neu-Binden“ und zum Anderen die Mutation“. Dabei<br />

” ”<br />

versteht man unter Neu-Binden die Änderung eines referenzierenden Bezeichners<br />

währenddessen Mutation die Veränderung eines referenzierten Wertes bezeichnet.<br />

Die Unterschiede zwischen den beiden Begriffen sollen anhand zweier Beispiele in der<br />

Programmiersprache Java verdeutlicht werden:<br />

Abbildung 3: Beispiel: Neu-Binden in der Programmiersprache Java<br />

Im obigen Beispiel wird in der ersten Zeile eine Referenz mit dem Namen list die ein<br />

Objekt vom Typ LinkedList referenzieren kann deklariert. Da in der Programmiersprache<br />

Java Referenzen standardmäßig mit dem Wert null“ 1 . initialisiert werden, wird<br />

”<br />

die Referenz list an den symbolischen Wert null gebunden. In der zweiten Zeile wird<br />

anschließend ein Objekt vom Typ LinkedList erzeugt und mittels des Gleichheitszeichen-<br />

Operators an die Referenz list gebunden. Es hat also ein Neu-Binden stattgefunden. In<br />

der darauf folgenden Zeile wird die Referenz explizit an den Wert null gebunden und<br />

es findet erneut ein Neu-Binden, also eine Änderung des referenzierenden Bezeichners,<br />

statt.<br />

Abbildung 4: Beispiel: Mutation in der Programmiersprache Java<br />

Das obige Beispiel für die Mutation ist bis auf die dritte Zeile mit dem vorhergehenden<br />

Beispiel für das Neu-Binden identisch. In der dritten Zeile jedoch wird durch<br />

1 In einigen <strong>Programmiersprachen</strong> existiert dieser spezielle Wert null oder auch NULL, der von der<br />

Ziffer 0 zu unterscheiden ist. Er hat die Bedeutung leer, unbestimmt, ohne Wert<br />

2.1 Neu-Binden und Mutation


2 WAS VERSTEHT MAN UNTER BINDEN ? 7<br />

das Hinzufügen eines Strings-Objektes in das verkettete Listen-Objekt, das verkettete<br />

Listen-Objekt geändert, d.h. der referenzierte Wert, also das Listen-Objekt LinkedList<br />

ändert sich. Es hat hier also die Veränderung eines referenzierten Wertes stattgefunden,<br />

eine Mutation.<br />

2.2 Zeitpunkt des Bindens<br />

Prinzipiell existieren zwei Zeitpunkte, an denen eine Referenz an ein Objekt gebunden<br />

werden kann. Das ist zum Einen, während der Kompilierung eines Programms und<br />

zum Anderen während der Laufzeit eines Programms. Die erste Möglichkeit, also Binden<br />

während der Kompilierung, wird auch als statische Bindung oder auch als frühes<br />

Binden (engl. static binding bzw. early binding), die zweite Möglichkeit, während der<br />

Laufzeit, als dynamisches oder spätes Binden (engl. dynamic binding bzw. late binding)<br />

bezeichnet.<br />

Unterschiede liegen für den Programmierer vor allen Dingen in der höheren Flexibilität<br />

und besseren Erweiterbarkeit bei Verwendung von dynamischen Binden, da während der<br />

Ausführung eines Programms Veränderungen möglich sind. Teilweise muss jedoch bei<br />

Lösungen die dynamisches Binden verwenden auch mit einer schlechteren Performanz<br />

gerechnet werden, da da der Compiler während der Kompilierung aufgrund der dynamischeren<br />

Natur des Programms weniger Annahmen treffen kann und damit weniger<br />

Möglichkeiten zur Optimierung besitzt.<br />

Um spätes Binden zu erreichen müssen verschiedene Sprachmittel eingesetzt werden.<br />

Diese unterscheiden sich je nachdem ob man eine dynamische Programmiersprache, wie<br />

beispielsweise Smalltalk oder Python, oder eine statische, wie beispielsweise Java oder<br />

C++, verwendet. Bei der Verwendung von dynamischen <strong>Programmiersprachen</strong> lässt<br />

sich spätes Binden durch die Anwendung der dynamischen Typisierung als Sprachmittel<br />

erreichen, während man bei den statischen <strong>Programmiersprachen</strong> das späte Binden<br />

mittels polymorphen Variablen bzw. Methoden ermöglicht werden kann.<br />

In den nachfolgenden zwei Abschnitten soll daher zuerst die Verwendung von dynamischer<br />

Typisierung und polymorpher Variablen gezeigt werden. In dem darauf folgenden<br />

Abschnitt soll dann gezeigt werden, wie man mit Hilfe dieser Sprachmittel spätes Binden<br />

in den unterschiedlichen <strong>Programmiersprachen</strong> ermöglichen kann.<br />

2.2 Zeitpunkt des Bindens


3 DYNAMISCHE TYPISIERUNG / STATISCHE TYPISIERUNG 8<br />

3 <strong>Dynamische</strong> Typisierung / Statische Typisierung<br />

Grundsätzlich bedeutet der Begriff statisch“ in Hinsicht auf <strong>Programmiersprachen</strong>,<br />

”<br />

daß das Binden während des Kompilierens stattfindet und danach keine Veränderungen<br />

mehr möglich sind (siehe [2]).<br />

Im Gegensatz dazu bedeutet dynamisch“ daß während der Ausführung eines Programms<br />

Veränderungen bezüglich des Bindens vorgenommen werden können.<br />

”<br />

In einer statisch typisierten Programmiersprache wie Java oder Pascal, findet Variablenbindung<br />

während des Kompilierens statt. Das bedeutet beispielsweise, daß die<br />

Variablen-Typen, also beispielsweise integer oder string zur Kompilierzeit festgelegt<br />

sind und sich während der Ausführung nicht mehr ändern können. Während des Kompilierens<br />

werden die Variablentypen an einer Stelle des Speichers gebunden. In einer<br />

dynamisch typisierten Programmiersprache wie beispielsweise Smalltalk oder Python<br />

dagegen, sind Variablen nur Bezeichner und deren Typen werden nur durch deren Werte<br />

definiert und nicht durch eine etwaige vorangegangene Typdeklaration. Die Bindung der<br />

verschiedenen Typen an einen Bezeichner erfolgt während der Programmausführung.<br />

Dies soll an dem folgenden Beispiel in der Programmiersprache Python verdeutlicht<br />

werden:<br />

Abbildung 5: Beispiel: <strong>Dynamische</strong> Typisierung in der Programmiersprache Python<br />

In diesem Beispiel ist der Bezeichner b nur ein Variablenname, der während der Laufzeit<br />

immer wieder neu an eine neue Speicherstelle und an einen neuen Variablentypen, zuerst<br />

an einen String und dann an einen Integer-Wert, gebunden wird. Dieses Verhalten ist<br />

möglich, da Python die Fähigkeit zur dynamischen Typisierung als Sprachmittel besitzt.


3 DYNAMISCHE TYPISIERUNG / STATISCHE TYPISIERUNG 9<br />

Es erfolgt im Gegensatz zu einer statischen Programmiersprache wie beispielsweise Java<br />

im Quell-Code keine Typ-Deklaration der einzelnen Variablen.<br />

In einer statisch typisierten Programmiersprache wie Java ist dies, wie das folgende<br />

Beispiel zeigt, nicht möglich:<br />

Abbildung 6: Beispiel: Statische Typisierung in der Programmiersprache Java<br />

Da die Variable b bereits im Kopf des Programms statisch als integer-Variable deklariert<br />

wurde, lässt sich ihr innerhalb der main-Methode kein String-Wert mehr zuweisen.<br />

Es kommt daher zu einem Kompilierfehler. Dies lässt sich sowohl als Nachteil- aber<br />

auch als Vorteil bezüglich des Beispiels mit dynamischer Typisierung betrachten. Ein<br />

Nachteil besteht darin, daß sich der Bezeichner b nicht wiederverwerten lässt, der<br />

Vorteil, daß durch die Typprüfung verhindert werden kann, daß nicht unbeabsichtigte<br />

Wertzuweisungen auftreten können.<br />

Ein weiteres Beispiel für dynamische Typisierung findet man in der Programmiersprache<br />

Objective-C, einer hauptsächlich von Brad Cox in den 80er Jahren bei PPI, später Stepstone,<br />

um die Fähigkeit der Objektorientierung entwickelten Erweiterung der Programmiersprache<br />

C. Deren Syntax und Konzeption der objektorientierten Erweiterungen ist<br />

an Smalltalk angelehnt. Bemerkenswerte Eigenschaften von Objective-C gegenüber der<br />

Programmiersprache C++, die ebenfalls einen Ansatz einer objektorientierten Erweiterung<br />

der Programmiersprache C darstellt (der jedoch auf Simula zurückgeht), sind<br />

u.a. das späte Binden von Methoden und die Typlosigkeit, die beide auf Smalltalk<br />

zurückgehen.<br />

Im unteren Beispiel wird ein Ausschnitt einer Klasse gezeigt, die einen Knoten in einer<br />

einfach verketteten Liste darstellen soll. Dabei ist das Attribut LinkedListNode*<br />

next ein Zeiger auf das nächste Element der Liste und das Attribut id data der Inhalt


3 DYNAMISCHE TYPISIERUNG / STATISCHE TYPISIERUNG 10<br />

den ein Listenelement speichern kann. Damit die Liste jeden beliebigen Typ aufnehmen<br />

kann, ist die Variable data vom Typ id. Id ist in ObjectiveC ein Variablentyp der alle<br />

Objekttypen aufnehmen kann, so daß die Liste alles speichern kann.<br />

Abbildung 7: Beispiel: <strong>Dynamische</strong> Typisierung in der Programmiersprache Objective-C<br />

3.1 Duck-Typing und die halbdynamische Sprache Boo<br />

Ein Beispiel für eine Sprache die sowohl dynamische Typisierung als auch statische<br />

Typisierung unterstützt ist die Programmiersprache Boo. Boo ist eine seit 2003 von<br />

Rodrigo Barreto de Oliveira entwickelte OpenSource-Programmiersprache für das Microsoft<br />

.NET Framework und die Java Virtual Machine (boojay). Die Syntax ist stark an<br />

die von Python angelehnt, da es das ursprüngliche Entwicklungsziel war, eine pythonähnliche<br />

Sprache zu entwickeln, die jedoch auch die Fähigkeit besitzt auf die .NET<br />

und JVM-Bibliotheken zugreifen zu können. Boo ist statisch typisiert, wobei dem Programmierer<br />

das explizite Binden von Variablen an Typen durch Typinferenz und Generische<br />

Typen großteils erspart wird. Daneben wird auch das langsamere, von Ruby<br />

übernommene Duck Typing 2 , also dynamische Typisierung geboten. Dadurch ist sie<br />

2 Duck-Typing ist ein Konzept der Objektorientierung, das die Anwendbarkeit bestimmter Verfahren<br />

nicht an die Ableitung der Klasse von einer bestimmten Superklasse oder der förmlichen Implementierung<br />

einer Spezifikation knüpft, sondern an das Vorhandensein bestimmter Merkmale. Der Name<br />

leitet sich aus einem Gedicht des amerikanischen Schriftsteller James Whitcomb Riley ab. Darin heißt<br />

es: ”When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call<br />

that bird a duck.”[6]<br />

3.1 Duck-Typing und die halbdynamische Sprache Boo


3 DYNAMISCHE TYPISIERUNG / STATISCHE TYPISIERUNG 11<br />

auf der explizit für statisch typisierte Sprachen ausgelegten CLR 3 recht schnell, ohne<br />

auf die Flexibilität einer dynamischen Skriptsprache verzichten zu müssen.<br />

Abbildung 8: Beispiel: Duck Typing in der Programmiersprache Boo[5]<br />

Im obigen Beispiel wird in der ersten Zeile die Variable d als eine Variable vom Typ<br />

duck deklariert. Eine Variable vom Typ duck kann in der Programmiersprache Boo<br />

jeglichen Wert annehmen. In der zweiten Zeile wird der Variablen dann ein Integer-<br />

Wert zugewiesen und in den nächsten Zeilen damit arithmetische Operationen und<br />

eine Bildschirmausgabe durchgeführt. Anschließend wird der Variablen ein String zugewiesen<br />

und anschließend eine String-Operation auf ihr ausgeführt. Wie man erkennen<br />

kann, ist das Verhalten der Variablen nur abhängig davon welchen Wert sie besitzt.<br />

Hier zeigt sich das Prinzip des Duck-Typings: ”<br />

Wenn es geht wie eine Ente, schwimmt<br />

wie eine Ente und quakt wie eine Ente, dann behandle ich es wie eine Ente“ .<br />

3 CLR - die Common Language Runtime ist eine von Microsoft entwickelte Softwareplattform.<br />

Diese umfasst eine Laufzeitumgebung, eine für Programmierer bestimmte Sammlung von Klassenbibliotheken<br />

(API), und angeschlossene Dienstprogramme (Services).<br />

3.1 Duck-Typing und die halbdynamische Sprache Boo


3 DYNAMISCHE TYPISIERUNG / STATISCHE TYPISIERUNG 12<br />

3.2 Vor- und Nachteile bei dynamischer / statischer Typisierung<br />

Grundsätzlich kann man feststellen, daß sich die Vor- und Nachteile bei dynamischer<br />

und statischer Typisierung gegenseitig die Waage halten. Die Vorteile die man bei<br />

statischer Typisierung besitzt sind gleichzeitig aber auch die Nachteile der statischen<br />

Typisierung. Das gleiche gilt umgekehrt auch für die dynamische Typisierung.<br />

Statische Typisierung<br />

• Vorteile:<br />

– bessere Fehlererkennung (während des Kompilierens)<br />

– schnellere Ausführungsgeschwindigkeit der Programme<br />

• Nachteile:<br />

– geringere Flexibilität<br />

– schlechtere Erweiterbarkeit / Wiederverwendbarkeit<br />

<strong>Dynamische</strong> Typisierung<br />

• Vorteile:<br />

– höhere Flexibilität<br />

– bessere Erweiterbarkeit / Wiederverwendbarkeit<br />

• Nachteile:<br />

– schlechtere Fehlererkennung<br />

– langsamerere Ausführungsgeschwindigkeit der Programme<br />

3.2 Vor- und Nachteile bei dynamischer / statischer Typisierung


4 POLYMORPHE VARIABLEN 13<br />

4 Polymorphe Variablen<br />

Statische <strong>Programmiersprachen</strong>, wie beispielsweise Java, können dynamisches Binden<br />

im Gegensatz zu dynamischen Sprachen wie Python, nicht mit Hilfe von dynamischer<br />

Typisierung erreichen, da ihnen dieses Sprachmittel fehlt. Um jedoch trotzdem dynamisches<br />

Binden bei Methoden zu ermöglichen wird dies durch Verwendung von Polymorphie<br />

4 und dabei insbesondere unter Verwendung von polymorphen Variablen und<br />

Methoden erreicht.<br />

Im nachfolgenden Beispiel wird gezeigt, wie ein Drucker-Objekt mittels Verwendung<br />

polymorpher Variablen sowohl an die Variable drucker vom Typ Drucker gebunden<br />

werden kann, als auch an die Variable ausgabegeraet (also an zwei unterschiedliche<br />

Variablentypen und nicht nur an einen bestimmten Typ). Diese Eigenschaft ermöglicht<br />

erst spätes Binden (late binding).<br />

Abbildung 9: Beispiel: Verwendung polymorpher Variablen<br />

Ausgabegeraet ausgabegeraet;<br />

Monitor monitor;<br />

Drucker drucker;<br />

ausgabegeraet<br />

ausgabegeraet<br />

= monitor; // OK<br />

= drucker; // OK<br />

drucker = ausgabegeraet; // nicht OK !<br />

4 Polymorphie (griechisch Vielgestaltigkeit) ist die Fähigkeit eines Bezeichners, der ein Literal oder<br />

eine Variable repräsentieren kann, sich abhängig von seiner Verwendung unterschiedlich darzustellen.<br />

Sie erlaubt es dem Bezeichner, je nach Kontext einen unterschiedlichen Datentyp anzunehmen.


5 DYNAMISCHE- / STATISCHE-BINDUNG 14<br />

5 <strong>Dynamische</strong>- / Statische-Bindung<br />

Statisches Methodenbinden bezeichnet das bereits im zweiten Abschnitt erwähnte statische<br />

Binden eines Bezeichners an eine Methode und ist die Standard-Aufrufweise<br />

bei statischen <strong>Programmiersprachen</strong> wie beispielsweise Java und C++ (zum Beispiel<br />

myObject.myMethod()). Das heißt, es existiert ein direkter Verweis auf die zu verwendete<br />

Methode bzw. Funktion während der Kompilierzeit.<br />

Die Voraussetzungen für statisches Methodenbinden sind zum Einen, daß die aufgerufene<br />

Methode zur Kompilierzeit existiert und deren Signatur dem Compiler bekannt<br />

sein muß und zum zweiten, daß die Bindung an zur Kompilierzeit bekannte Typen,<br />

Interfaces oder Oberklassen erfolgen muß.<br />

Abbildung 10: Beispiel: UML-Diagramm Klassenhierarchie bei Polymorphie


5 DYNAMISCHE- / STATISCHE-BINDUNG 15<br />

Ein Beispiel für dynamisches Binden in Java:<br />

Abbildung 11: Beispiel: <strong>Dynamische</strong>s Binden in Java


5 DYNAMISCHE- / STATISCHE-BINDUNG 16<br />

Bei dynamischer Bindung erfolgt die Bindung nicht durch den Aufruf einer Referenz der<br />

Implementierung, sondern durch das Schicken von Nachrichten an ein Object (message<br />

passing / dynamic dispatch). Das Object selbst schaut dabei zur Laufzeit nach, ob es<br />

eine passende Implementierung (Methode) besitzt, die zur Nachricht passt. Falls es<br />

diese nicht besitzen sollte, kann es entweder eine Fehlermeldung ausgeben oder die<br />

Nachricht an ein anderes Objekt weiterschicken, was als forwarding bezeichnet wird.<br />

Ein Beispiel in Objective-C: Nach dem Beginn der main-Funktion wird eine Variable<br />

namens ausgabegeraet deklariert die vom Typ id ist. Der spezielle Variablen-Typ id<br />

besitzt in Objective-C die Eigenschaft, daß er jedes Objekt binden kann. Durch diese<br />

Art der Typisierung kann dann im weiteren Verlauf des Programmes der Variablen<br />

ausgabegeraet sowohl ein Objekt vom Typ Monitor als auch vom Typ Drucker zugewiesen<br />

werden, da die Variable ausgabegeraet ja vom Typ id ist. Anschließend kann<br />

an die Variable ausgabegeraet dann die Nachricht ausgabe geschickt werden und das<br />

dahinterstehende Objekt (also drucker bzw. monitor) führt die Methode ausgabe anschließend<br />

aus. Es ist kein Polymorphismus nötig wie in Java, da Objective C eine<br />

dynamische Sprache ist.<br />

Abbildung 12: Beispiel: <strong>Dynamische</strong>s Binden in Objective-C


5 DYNAMISCHE- / STATISCHE-BINDUNG 17<br />

Auch bei Python ist, ähnlich wie bei Objective-C, kein Polymorphysmus notwendig<br />

um Late-Binding zu erreichen. In dem folgenden Beispiel werden die Klassen Monitor<br />

und Drucker deklariert, die beide die Methode ausgabe() besitzen. Danach werden<br />

im Hauptprogramm zwei Instanzen (Objekte) der beiden Klassen erzeugt. Anschließend<br />

wird, was aufgrund der dynamischen Typsierung der Programmiersprache Python<br />

möglich ist, einfach einer neu eingeführten Variablen namens ausgabegeraet entweder<br />

das Monitor-Objekt oder das Drucker-Objekt zugewiesen. Daraufhin kann über die<br />

Referenz ausgabegeraet die Methode ausgabe des entsprechenden Objekts aufgerufen<br />

werden.<br />

Abbildung 13: Beispiel: <strong>Dynamische</strong>s Binden in Python


5 DYNAMISCHE- / STATISCHE-BINDUNG 18<br />

5.1 Unterschiede zwischen dynamischer und statischer Bindung<br />

Statisches Methodenbinden ist schneller, da es zum einen keinen Overhead bezüglich<br />

des Methodenaufrufs gibt und zum anderen Inlining 5 möglich ist. Daß kein Overhead<br />

bei statischem Methodenbinden bezüglich des Methodenaufrufs vorhanden ist, ergibt<br />

sich aus der Tatsache, daß der Computer nicht mehr während der Laufzeit des Programmes<br />

suchen muß, wo (Methoden können beispielsweise in Objective-C per forwarding<br />

in anderen Klassen aufgerufen werden) und welche Methode (Methoden können<br />

sich in Ober- oder Unterklassen befinden) er erst aufrufen muss. Dies erfolgt beim<br />

statischem Methodenbinden alles schon während der Kompilierzeit. Dadurch ist außerdem<br />

auch Inlining möglich, was bedeutet, daß der Compiler während des Kompilierens<br />

die komplette Methode an die Stelle des Methodenaufrufs setzt, so daß der Rechner<br />

während der Laufzeit nicht mehr mit großem Aufwand zwischen den Methoden hinund<br />

herspringen muß. Dies macht sich insbesondere innerhalb von Schleifen bemerkbar.<br />

So kann man sich vorstellen, daß sich schon ein erheblicher Unterschied ergibt,<br />

ob der Computer innerhalb einer Schleife, die 1 Million mal ausgeführt wird, zwischen<br />

zwei Funktionen, mit entsprechender Parameterübergabe über den Stack, hin- und herspringen<br />

muß, oder ob der Code der Funktion einfach innerhalb der Schleife eingesetzt<br />

wurde. C++ besitzt das Schlüsselwort inline für Funktionen / Methoden mit dem man<br />

dem Compiler anzeigen kann, daß man die damit markierte Methode / Funktion als<br />

inline-Funktion haben will.<br />

Bei dynamischer Bindung ergibt sich das Problem, daß der Compiler während des<br />

Kompiliervorgangs noch nicht wissen kann, ob und wann eine Methode überhaupt aufgerufen<br />

wird und er auch nicht sagen kann, ob die Übergabe- und Rückgabetypen<br />

überhaupt zueinanderpassen. Das heißt, daß bei dynamischen <strong>Programmiersprachen</strong><br />

eventuell Fehler erst während der Laufzeit auftreten, die in statischen <strong>Programmiersprachen</strong><br />

schon während des Kompilierens auffallen und korrigiert werden können bevor<br />

das Programm ausgeliefert wird.<br />

5 Bei kleinen Unterprogrammen fällt der Aufwand zum Aufruf des Unterprogrammes verglichen<br />

mit der vom Unterprogramm geleisteten Arbeit stärker ins Gewicht. Daher versuchen Compiler, den<br />

Maschinencode kleinerer Unterprogramme direkt einzufügen. Diese Technik wird auch als Inlining<br />

bezeichnet. In manchen <strong>Programmiersprachen</strong> ist es möglich, durch inline-Schlüsselwörter den Compiler<br />

darauf hinzuweisen, dass das Einfügen von bestimmten Unterprogrammen gewünscht ist. Das<br />

Einfügen von Unterprogrammen eröffnet oft, abhängig von den Parametern, weitere Möglichkeiten<br />

für Optimierungen.<br />

5.1 Unterschiede zwischen dynamischer und statischer Bindung


6 FAZIT 19<br />

6 Fazit<br />

In dieser Seminarbeit wurde versucht die Begriffe dynamisch“ und statisch“ im Kontext<br />

von <strong>Programmiersprachen</strong> und des Zeitpunkt des Bindens darzulegen. Weiterhin<br />

” ”<br />

sollten die Vor- und Nachteile von dynamischer - und statischer Typisierung aufgezeigt<br />

und deren Verwendung als Sprachmittel in Hinsicht auf die Realisierung von<br />

frühem und spätem Binden gezeigt werden. Auch sollte gezeigt werden, daß man den<br />

grundsätzlichen Widerspruch zwischen den Vor- und Nachteilen von dynamischer und<br />

statischer Programmierung nicht auflösen kann und sich je nach Anwendung für die<br />

für das Projekt passende Variante entschieden werden muss.<br />

Grundsätzlich kann man festhalten, daß, wenn man auf die Performanz der Ausführung<br />

und eine bessere Fehlererkennung der Programmen Wert legt, man statische Programmierung<br />

bevorzugen sollte, falls höhere Flexibilität, Erweiterbarkeit und Produktivität<br />

gewünscht wird, dynamische Programmierung.


LITERATUR 20<br />

Literatur<br />

[1] Binding (computer science) - Wikipedia<br />

http://en.wikipedia.org/wiki/Binding (computer science)<br />

Zugriffsdatum: 02.12.2008<br />

[2] Dai, L.: Static and Dynamic Behavior<br />

http://www.seattleu.edu/dingle/web/510/chapter11.ppt<br />

acstaff, 2007<br />

Zugriffsdatum: 02.12.2008<br />

[3] Anonymous: Dynamic binding, binding evaluation contexts, and (delimited) control<br />

effects<br />

http://www.okmij.org/ftp/Computation/dynamic-binding.html<br />

okmij.org, 2007<br />

Zugriffsdatum: 02.12.2008<br />

[4] H.-C. Stotts: Dynamic Method Binding, Inheritance<br />

http://www.rockfish.cs.unc.edu/COMP144/lect24a.ppt<br />

University of North Carolina, 2007<br />

Zugriffsdatum: 02.12.2008<br />

[5] Rodrigo Barreto de Oliveira: Boo Tutorial Part 18 - Duck Typing<br />

http://boo.codehaus.org/Part+18+-+Duck+typing<br />

Zugriffsdatum: 02.12.2008<br />

[6] Duck-Typing - Wikipedia<br />

http://de.wikipedia.org/wiki/Duck-Typing<br />

Zugriffsdatum: 02.12.2008<br />

LITERATUR


ABBILDUNGSVERZEICHNIS 21<br />

Abbildungsverzeichnis<br />

1 Beispiel: Binden in Python . . . . . . . . . . . . . . . . . . . . . . . . 3<br />

2 Beispiel: Funktionsbindung in der Programmiersprache C . . . . . . . . 4<br />

3 Beispiel: Neu-Binden in der Programmiersprache Java . . . . . . . . . 6<br />

4 Beispiel: Mutation in der Programmiersprache Java . . . . . . . . . . . 6<br />

5 Beispiel: <strong>Dynamische</strong> Typisierung in der Programmiersprache Python . 8<br />

6 Beispiel: Statische Typisierung in der Programmiersprache Java . . . . 9<br />

7 Beispiel: <strong>Dynamische</strong> Typisierung in der Programmiersprache Objective-C 10<br />

8 Beispiel: Duck Typing in der Programmiersprache Boo[5] . . . . . . . 11<br />

9 Beispiel: Verwendung polymorpher Variablen . . . . . . . . . . . . . . 13<br />

10 Beispiel: UML-Diagramm Klassenhierarchie bei Polymorphie . . . . . . 14<br />

11 Beispiel: <strong>Dynamische</strong>s Binden in Java . . . . . . . . . . . . . . . . . . 15<br />

12 Beispiel: <strong>Dynamische</strong>s Binden in Objective-C . . . . . . . . . . . . . . 16<br />

13 Beispiel: <strong>Dynamische</strong>s Binden in Python . . . . . . . . . . . . . . . . 17<br />

ABBILDUNGSVERZEICHNIS

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

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!