Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Telecooperation/RBG Technische Universität Darmstadt Copyrighted material; for TUD student use only Grundlagen der Informatik I Thema 17: Statische Typisierung.

Ähnliche Präsentationen


Präsentation zum Thema: "Telecooperation/RBG Technische Universität Darmstadt Copyrighted material; for TUD student use only Grundlagen der Informatik I Thema 17: Statische Typisierung."—  Präsentation transkript:

1 Telecooperation/RBG Technische Universität Darmstadt Copyrighted material; for TUD student use only Grundlagen der Informatik I Thema 17: Statische Typisierung Subtyp-Polymorphie Prof. Dr. Max Mühlhäuser Dr. Guido Rößling

2 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Worum geht es in dieser Vorlesung? Das magische Dreieck der Programmiersprachen 2 sicher einfach mächtig Welche Invarianten gibt es in meinem Programm? Wie einfach ist ein Programm zu verstehen? Welche Ideen können in der Sprache direkt ausgedrückt werden? Wir hatten diese Abwägung schon mal: Die Diskussion pro/contra Zuweisungen

3 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Werte und Typen Definition: Ein Typ ist eine Menge von Werten, die irgendeine interessante gemeinsame Eigenschaft haben –Gemeinsame Eigenschaften gemeinsame Operationen! Ist ein Wert v Element eines Typs T, sagen wir v hat den Typ T Beispiel: {0,1,2,…} ist ein Typ: die natürlichen Zahlen –Beispiel: {1,2,3,4,5,6} ist ein Typ: die Menge der deutschen Schulnoten –Ein Wert kann zu mehreren Typen passen Andere Typen: Symbol, String, … 3

4 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Werte und Typen Viele Abstraktionsmechanismen in Programmiersprachen beruhen auf der Abstraktion Wert Typ –Wir abstrahieren (* 4 4), (* 3 3) zu (square 4), (square 3), wobei square = (lambda (x) (* x x)) –Wir gehen implizit davon aus, dass das x in der Funktionsdefinition den Typ Number hat, denn nur für diesen ist * definiert Funktionen haben ebenfalls einen Typ, den wir mit Hilfe von Verträgen ausgedrückt haben –z.B. (lambda (x) (* x x)) hat den Typ number number 4

5 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Typfehler Ein Typfehler tritt auf, wenn eine berechnende Einheit (z.B. ein Wert oder eine Funktion) in einer zu dem Konzept, das sie darstellt, inkonsistenten Art und Weise benutzt wird –Hardwarefehler unerlaubter Instruktionsfehler unerlaubter Speicherverweis –Versehentliche Semantik z.B. kann in int_add(3, 4.5) der Wert 4.5 falsch interpretiert werden als ein Ganzzahlwert, der nicht mit 4.5 in Beziehung steht 5

6 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Typsysteme Ein Typsystem ist ein Mechanismus, der jedem Wert einen Typ (oder Menge von Typen) zuordnet und verhindert, dass Typfehler auftreten. 6 Beispiel: Scheme verhindert den Typfehler durch Abbruch des Programms Diese Fehlermeldung bekommen wir aber erst, wenn wir das Programm ausführen! > (define x 'hello) > (+ x 5) +: expects type as 1st argument, given: 'hello; other arguments were: 5

7 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Statische Typsysteme In einem statischen Typsystem kann man ein Programm vor der Ausführung auf mögliche Typfehler überprüfen –Ein großer Vorteil, weil man den Fehler bemerkt, bevor es zu spät ist –Zuverlässiger als Testen, weil Tests nur die Anwesenheit, aber nicht die Abwesenheit von Fehlern überprüfen können In kompilierten Sprachen geschieht diese Typüberprüfung häufig während der Kompilierung Auch interpretierte Sprachen können aber statische Typsysteme haben Beispiel für statisch typisierte Sprache: Java 7

8 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Statische Typsysteme Werden Typfehler erst zur Laufzeit erkannt, spricht man von dynamisch typisierten Sprachen Werden Typfehler gar nicht erkannt, spricht man von untypisierten Sprachen –Beispiel: Assembler In der Realität werden viele Programmiersprachen statisch geprüft, garantieren aber keine Sicherheit (manchmal schwaches Prüfen genannt) Manche Sprachen haben ein statisches Typsystem, welches aber nicht alle Typfehler erkennt –gut genug, 80/20 Regel 8

9 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Ebenen von Typsicherheit 9

10 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 class Counter { int n; Counter(int value) { n = value; } //... } Statisch typisierte Sprachen Beispielsprachen: Java, C++, C#, Haskell, ML Der Typ jeder Variable kann zur Kompilierzeit bestimmt werden –Die meisten statisch typisierten Sprachen erreichen dieses Ziel, indem sie explizite Deklarationen der Typen verlangen. 10 Es ist in Java unmöglich, eine Variable zu deklarieren, ohne ihren Typ anzugeben.

11 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Statisch typisierte Sprachen Statisch typisierte Sprachen mit impliziten Deklarationen verwenden vorgegebene Konventionen –FORTRAN: Variablen, die mit I, J, K, L, M, N anfangen, enthalten Ganzzahlen Es gibt statisch typisierte Sprachen mit Typdeduktionsfähigkeiten (type inference) –Gegeben folgende Deklaration, kommt der ML-Compiler zu der Folgerung, dass x eine Zahl ist. 11 fun square(x) = x * x

12 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Dynamisch typisierte Sprachen In dynamisch typisierten Sprachen wird der Typ einer Variable dynamisch gebunden Es sind keine Typdeklarationen notwendig. Sehr bequem! Ermöglicht die Definition von flexiblen Funktionen, für die der Typ der Argumente egal ist. Beispiele: –Scheme, Smalltalk, Self, Python, etc. 12

13 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Typprüfung Typprüfung stellt sicher, dass die Operanden eines Ausdrucks kompatibel mit den Operatoren sind –Sowie dass es sich bei einer Nachricht an einem Objekt um eine Methode in der Schnittstelle des Objektes handelt Kompatible Typen sind entweder die gleichen Typen, oder können implizit ineinander konvertiert werden. –Automatische Typkonvertierung wird coercion genannt –Siehe die Diskussion über automatische Typkonvertierungen in Abschnitt SICP (V 9) –integer rational real complex Ein Typfehler entsteht bei der Anwendung einer Operation an einem Operanden mit einem unerlaubten Typ. 13

14 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Typprüfung Bei statischen Typbindungen kann die Typprüfung statisch (zur Kompilierzeit) stattfinden (statische Typprüfung). Bei dynamischen Typbindungen kann die Typprüfung nur zur Laufzeit geschehen (dynamische Typprüfung). In einigen statisch typisierten Sprachen können einige Typprüfungen auch nur zur Laufzeit durchgeführt werden –Mehr dazu später 14

15 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Statische vs. dynamische Typprüfung 15 String x = "hello"; x = x * 10; Zur Kompilierzeit: x = x * 10; ^^^^^^ * not defined for type String (define x 'hello) (+ x 1) Zur Laufzeit: +: expects type as 1st argument, given: hello; other arguments were: 1 Ungültige Verwendung von Variablen werden von dem Compiler nicht entdeckt und führen zu einem Laufzeitfehler

16 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Statische vs. dynamische Typprüfung 16 String s = new String("Hello World"); s.determineLength(); Compile program… Error in... (line 3) s.determineLength(); ^^^^^^^^^^^^^^^^ Method determineLength() not defined for type String

17 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Statische vs. dynamische Typprüfung 17 (define (make-counter n) (define (increment) (set! n (+ n 1)) n) (define (dispatch msg) (cond ((eq? msg 'increment) increment) (else (error "undef operation:" msg))) ) dispatch ) (define ca (make-counter 1)) (ca 'increment) (ca 'decrement) Zur Laufzeit: undef operation: decrement

18 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Statisches Typisieren ist konservativ Ein perfekter statischer Typprüfer wäre ein Typprüfer, der einen Typfehler dann und genau dann meldet, wenn der Typfehler während der Programmausführung auftreten wird Ein perfekter Typprüfer existiert nicht! –Folgt aus bestimmten Unentscheidbarkeitsergebnissen aus der Theoretischen Informatik (Halteproblem) Somit nähern statische Typprüfer das Laufzeitverhalten an: Sie sind konservativ –Sie bleiben auf der sicheren Seite –Wann immer ein Typfehler zur Laufzeit auftreten würde, wird er vom Typprüfer entdeckt –Es gibt aber auch Programme, die vom Typprüfer abgelehnt werden, die ohne Fehler ausgeführt werden könnten 18

19 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Sollten Sprachen statisch geprüft werden? Argumente für statisches Prüfen Wirtschaftlichkeit der Ausführung –z.B. arithmetisch, Methodenauflösung Wirtschaftlichkeit des Kompilierens –separate Kompilierung möglich Wirtschaftlichkeit der Entwicklung in kleinem Umfang –kann einen großen Teil von Routineprogrammierfehlern abfangen, besser als unvollständiges manuelles Testen –bietet Dokumentation zum Quelltext an –Gebrauch des Typprüfers als Entwicklungswerkzeug, z.B. eine Klasse umbenennen, um alle Referenzen darauf zu entdecken Wirtschaftlichkeit der Entwicklung im großen Umfang –Teams können Schnittstellen vereinbaren, die vom Compiler erzwungen werden –Abstrahieren weg von der Implementierung großer Komponenten 19

20 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Sollten Sprachen statisch geprüft werden? Argumente gegen statisches Prüfen Quelltext langatmiger –viele offensichtliche Deklarationen Inflexibilität –Statisches Prüfen ist konservativ –probieren Sie das z.B. in Java Identitätsfunktion implementieren ohne Typumwandlung Das Argument von equals(Object other) sollte den selben Typ haben wie der Empfänger clone() gibt immer eine Instanz desselben Typs wie der Empfänger zurück Viele Mechanismen wurden entwickelt, um mit diesen Problemen umzugehen –Typinferenz, Typsysteme höherer Ordnung,... –Aber diese Mechanismen können sehr komplex sein 20 Ein statischer Typprüfer ist ein mächtiger Helfer, solange die Programme in den Grenzen dessen liegen, was das Typsystem ausdrücken kann. Wenn wir über diese Grenzen hinausgehen wollen, steht uns das Typsystem im Weg.

21 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Statischer und dynamischer Typ Der Typ eines Objekts ist immer die Klasse, deren Instanz es ist – dieser Typ ist immer dynamisch an ein Objekt gebunden. Bei Variablen unterscheiden wir den statischen und dynamischen Typ: –Der statische Typ einer Variablen ist der Typ, an den sie bei der Deklaration gebunden wird. Er verändert sich während der Ausführung nicht. –Der dynamische Typ zu einem Zeitpunkt t während der Ausführung ist der Typ des Objekts, auf das die Variable zum Zeitpunkt t verweist. 21

22 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Statischer und dynamischer Typ 22 Hier wird in einem Programm ein und derselbe Name an verschiedenen Stellen benutzt, um zwei verschiedene Objekte zu bezeichnen. Eine solche Variable nennt man polymorph (griechisch "vielgestaltig"). In der realen Welt gibt es mehrere Objekte namens shape, und welches gemeint ist, hängt vom Kontext ab. In der Welt der grafischen Objekte ist es genauso. Statischer Typ der Variablen shape Der dynamische Typ der Variablen shape ist zu diesem Zeitpunkt Circle Der dynamische Typ von shape ist ab diesem Zeitpunkt Rectangle Shape shape = null; shape = new Circle(10, 20, 16); shape.draw(canvas); shape = new Rectangle(10, 10, 20, 5); shape.draw(canvas);

23 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 public void main(String[] args) { Circle shape = null; shape = new Rectangle(10, 10, 20, 5); //... } Statischer und dynamischer Typ Kann man ein grafisches Objekt beliebigen Typs an eine beliebige Variable zuzuweisen? –Natürlich nicht! Darum geht es ja bei Typsystemen: Ein Typ regelt, wie ein Name benutzt werden kann Der Typ schränkt die Menge der Werte ein, die einer Variablen zugewiesen werden können … und die darauf ausführbaren gültigen Operationen –Nur Instanzen einer direkten oder indirekten Subklasse ihres statischen Typs können an eine Variable zugewiesen werden. 23 H

24 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Das Substitutionsprinzip Ein Objekt (grafisches Objekt) einer Subklasse kann überall dort verwendet werden, wo ein Objekt (grafisches Objekt) einer Superklasse erwartet wird. Diese Substituierbarkeitsrelation ist transitiv. 24 An var kann jedes Objekt der Klassen B, C und all ihrer Subklassen zugewiesen werden (Transitivität der Substituierbarkeit). Jede in A und B deklarierte Operation kann auf var (auf jedem in var gespeicherten Objekt) aufgerufen werden. Es ist nicht erlaubt, auf var eine Operation aufzurufen, die in C deklariert ist, aber nicht in A oder B. A B C Die Deklaration B var; impliziert:

25 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Das Substitutionsprinzip Ein Objekt einer Subklasse kann einem Objekt einer Superklasse als Repräsentant dienen: –Seine Struktur enthält alle Attribute eines Objekts der Superklasse –Es kann alle Operationen ausführen, die für Objekte der Superklasse definiert wurden Das Gegenteil trifft jedoch nicht zu! –Ein Objekt einer Superklasse ist nicht spezialisiert genug, um die Rolle des Objekts einer Subklasse zu spielen. 25 Die Deklaration B var; heißt nicht var hat genau den Typ B ; sondern das Verhalten von var ist konform zu B.

26 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Substitutionsprinzip: eine Analogie 26 Ein Kunde einer Autovermietung bestellt ein vierrädriges Fahrzeug zum Transport einiger Möbelstücke von A nach B Es ist in Ordnung, wenn er einen Kleinbus erhält. Ein Kleinbus hat vier Räder. Hat er jedoch einen Lastwagen bestellt, dann ist es nicht OK, ihm ein beliebiges vierrädriges Fahrzeug zu geben Der Kleinbus könnte zu wenig Ladefläche haben. Fahrzeug ZweirädrigVierrädrig Motorrad Fahrrad Lastwagen Kleinbus

27 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Shape shape = null; shape = new Circle(10, 20, 16); shape.draw(canvas); shape = new Rectangle(10, 10, 60, 20); shape.draw(canvas); Subtyp-Polymorphie 27 Gleicher Programmtext, aber verschiedene Bedeutung POLYMORPHIE

28 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Subtyp-Polymorphie 28 Jedes grafische Objekt befolgt Befehle gemäß seiner Programmierung: paint(g); Circle vs. Rectangle Dies ist besonders interessant, wenn mehrere grafische Objekte dieselben Befehle erhalten, sie aber unterschiedlich implementieren.

29 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Noch einmal Subtyp-Polymorphie 29 Nun, da wir Schnittstellen kennen, betrachten wir statische und dynamische Typen von Variablen, Subtyp- Polymorphie und Substituierbarkeit gemeinsam. Zu diesem Zweck werden wir das UML- Klassendiagram auf dieser Folie benutzen. Es zeigt eine einfache Typ- und Klassenhierarchie.

30 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Noch einmal Subtyp-Polymorphie 30 Obwohl das Modell "Klassendiagramm" genannt wird, ist es eigentlich ein Typdiagramm. Jede Java-Klasse und Schnittstelle deklariert einen benutzerdefinierten Datentyp. Das Modell stellt fünf Typen dar: vier Klassen und eine Schnittstelle.

31 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Noch einmal Subtyp-Polymorphie 31 Von einem implementierungs- unabhängigen (also typorientierten) Standpunkt aus betrachtet, repräsentiert jedes der fünf Rechtecke einen Typ. Vom Standpunkt der Implementierung aus betrachtet, sind vier dieser Typen durch Klassen definiert, und einer durch eine Schnittstelle.

32 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Implementierungs-Hierarchie 32 class Base { public String m1() { return "Base.m1()"; } public String m2(String s) { return "Base.m2(" + s + ")"; } } interface Itype { String m2(String s); String m3(); } class Derived extends Base implements Itype { public String m1() { return "Derived.m1()"; } public String m3() { return "Derived.m3()"; } }

33 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Implementierungs-Hierarchie 33 class Derived2 extends Derived { public String m2(String s) { return "Derived2.m2(" + s + ")"; } public String m4() { return "Derived2.m4()"; } } class Separate implements IType { public String m1() { return "Separate.m1()"; } public String m2(String s) { return "Separate.m2(" + s + )"; } public String m3() { return "Separate.m3()"; } }

34 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Referenzen als Bullaugen 34 Derived2 derived2 = new Derived2(); Dieser Ausdruck tut zweierlei: er deklariert die explizit getypte Referenzvariable derived2, bindet derived2 an ein neu erzeugtes Derived2 -Objekt. Die Derived2 -Referenz kann als Menge von Bullaugen gesehen werden, durch die das Derived2 -Objekt gesehen wird. Es gibt ein Bullauge pro Operation im Typ Derived2. Das Derived2 -Objekt bildet jede Derived2 -Operation auf geeigneten Code ab, wie in der Implementierungs-Hierarchie vorgesehen.

35 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Referenzen als Bullaugen 35 Derived2 derived2 = new Derived2(); Beispiel: Das Derived2 -Objekt bildet m1() auf Code ab, der in der Klasse Derived definiert ist. Darüber hinaus überschreibt dieser Code die Implementierung von m1() in der Klasse Base. Eine Derived2 -Referenzvariable kann auf die überschriebene Methode m1() in Base nicht zugreifen. Der implementierende Code in der Klasse Derived kann aber die Implementierung in Base über super.m1() benutzen. Was die Referenzvariable derived2 angeht, ist dieser Code jedoch nicht sichtbar.

36 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Mehrere Referenzen auf ein Objekt 36 Substituierbarkeit: Wir können das Derived2 -Object, das an die Referenz derived2 gebunden ist, mit jeder Variablen eines Typs T referenzieren, wenn Derived2 zu T konform ist. Die Typhierarchie ergibt, dass Derived, Base, und IType Supertypen von Derived2 sind, Derived2 also zu ihnen konform ist. Daher kann z. B. eine Base -Referenz an das von derived2 referenzierte Objekt gebunden werden. Base base = derived2; ergibt eine weitere Menge von Bullaugen

37 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Mehrere Referenzen auf ein Objekt 37 Es findet keine Veränderung an dem Derived2 -Objekt oder seinen Operations-Abbildungen statt. Werden m1() oder m2(String) auf derived2 oder base aufgerufen, wird jeweils derselbe Code ausgeführt. String tmp; tmp = derived2.m1(); // Derived2 reference // tmp is "Derived.m1()" tmp = derived2.m2("Hello"); // tmp is "Derived2.m2(Hello)" tmp = base.m1(); // Base reference // tmp is "Derived.m1()" tmp = base.m2("Hello"); // tmp is "Derived2.m2(Hello)"

38 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Mehrere Referenzen auf ein Objekt Warum erhält man trotz verschiedener Referenzen identisches Verhalten? Ein Objekt weiß nicht, wer oder was seine Methoden aufruft. –Ein Derived2 -Objekt weiß nur, dass es, wenn es aufgerufen wird, den "Marschregeln" folgen muss, die von seiner Implementierungs-Hierarchie vorgegeben sind. Methoden-Auswahl (method dispatch) Diese Regeln legen fest, dass das Derived2 -Objekt für die Methode m1() den in der Klasse Derived, und für m2(String) den in Derived2 definierten Code ausführen muss. –Die vom referenzierten Objekt ausgeführte Aktion hängt nicht vom Typ der Referenzvariablen ab. 38

39 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Mehrere Referenzen auf ein Objekt 39 String tmp; // Derived2 reference tmp = derived2.m3(); // tmp is "Derived.m3()" tmp = derived2.m4(); // tmp is "Derived2.m4()" // Base reference tmp = base.m3(); // Compile-time error tmp = base.m4(); // Compile-time error Es findet keine Veränderung an dem Derived2 -Objekt oder seinen Operations-Abbildungen statt. Jedoch kann auf die Methoden m3() und m4() nicht mehr durch die Referenz base zugegriffen werden.

40 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Mehrere Referenzen auf ein Objekt 40 Das Derived2 -Objekt kann immer noch Aufrufe von m3() und m4() entgegen nehmen. Typrestriktionen, die solche Aufrufe über die Base -Referenz verhindern, treten zur Compilezeit auf. Die statische Typprüfung verhält sich wie ein Schild, indem sie Interaktionen zwischen Objekten nur durch explizit deklarierte Typ-Operationen erlaubt. Die statischen Typen der Referenzen definieren die Grenzen der Objektinteraktion. Das kann generalisiert werden: wird eine Supertyp-Referenz an ein Objekt gebunden, so wird dessen Benutzung eingeschränkt. Warum sollte ein Entwickler sich dafür entscheiden, Objekt- Funktionalität zu verlieren?

41 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Mehrere Referenzen auf ein Objekt Diese Entscheidung wird oft unfreiwillig gefällt. Angenommen, eine Referenzvariable ref ist an ein Objekt gebunden, dessen Klasse folgende Methodendefinition enthält: 41 public String poly1(Base base) { return base.m1(); } Folgender Aufruf ist erlaubt, weil der Parametertyp konform ist: ref.poly1(derived2); Durch den Methodenaufruf wird eine lokale Base -Referenz an das übergebene Objekt gebunden.

42 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Mehrere Referenzen auf ein Objekt Vom Standpunkt des Aufrufers, der das Derived2 -Objekt übergibt, führt das Binden einer Base -Referenz durch den Implementierer von poly1(Base) zu einem Verlust von Funktionalität. Für Implementierer sieht jedes an poly1(Base) übergebene Objekt wie ein Base -Objekt aus. –Den Implementierer kümmert es nicht, dass mehrere Referenztypen auf dasselbe Objekt zeigen können –Für ihn wird ein und derselbe Referenztyp an alle Objekte gebunden, die an die Methode übergeben werden. –Dass diese Objekte möglicherweise verschiedenen Typs sind, ist zweitrangig. –Der Implementierer erwartet nur, dass das jeweilige Objekt alle Operationen des Typs Base auf entsprechende Implementierungen abbilden kann. 42

43 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Eine Referenz auf mehrere Objekte Interessantes polymorphes Verhalten tritt auf, wenn eine Referenzvariable nacheinander an mehrere Objekte ggf. unterschiedlichen Typs gebunden wird. –Streng genommen, meint Objekttyp genau den durch die Klasse des Objekts definierten Typ. 43 Derived2 derived2 = new Derived2(); Derived derived = new Derived(); Base base = new Base(); String tmp; tmp = ref.poly1(derived2); // tmp is "Derived.m1()" tmp = ref.poly1(derived); // tmp is "Derived.m1()" tmp = ref.poly1(base); // tmp is "Base.m1()"

44 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Eine Referenz auf mehrere Objekte 44 Verschiedene Objekte werden durch dasselbe Bullauge betrachtet: –Das Bullauge definiert die Abbildungen, die verfügbar sein sollten –Verschiedene Objekte haben verschiedene Abbildungen.

45 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Die Macht der Polymorphie 45 Der Code von poly1(Base) betrachtet jedes Objekt durch eine Base -Typ-Linse. Wird jedoch ein Derived2 -Objekt übergeben, gibt die Methode ein Ergebnis zurück, das von Code in der Klasse Derived berechnet wurde! Werden die Klassen Base, Derived oder Derived2 später erweitert, wird poly1(Base) problemlos Objekte der neuen Klassen akzeptieren und den erwünschten Code ausführen. Polymorphie gestattet, dass die neuen Klassen lange nach der Implementierung von poly1(Base) hinzu kommen.

46 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Die Macht der Polymorphie Wie geht das? Vom typorientierten Standpunkt aus ist der eigentliche Implementierungscode referenzierter Objekte unerheblich. –Der wichtigste Aspekt der Bindung von Referenzen an Objekte ist der, dass durch die zur Compilezeit stattfindende Typprüfung garantiert werden kann, dass das referenzierte Objekt für jede Operation des Typs eine zur Laufzeit verfügbare Implementierung besitzt. Polymorphie befreit den Entwickler von der Pflicht, Implementierungsdetails einzelner Objekte zu kennen, und erlaubt statt dessen, einen Entwurf allein aus einer Typ- orientierten Perspektive anzufertigen. –Darin liegt ein signifikanter Vorteil der Trennung von Typ und Implementierung (auch genannt "Trennung von Schnittstelle und Implementierung"). 46

47 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Java-Schnittstellen und Polymorphie Java-Schnittstellen deklarieren benutzerdefinierte Typen –Entsprechend erlauben Java-Schnittstellen polymorphes Verhalten durch den Aufbau einer Typvererbungsstruktur. 47 public String poly2(IType iType) { return iType.m3(); } Angenommen, eine Referenzvariable ref wird an ein Objekt gebunden, dessen Klasse folgende Methode enthält: Das Folgende illustriert polymorphes Verhalten in poly2(IType): Derived2 derived2 = new Derived2(); Separate separate = new Separate(); String tmp; tmp = ref.poly2(derived2); // tmp is "Derived.m3()" tmp = ref.poly2(separate); // tmp is "Separate.m3()"

48 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Java-Schnittstellen und Polymorphie Vom Typ-orientierten Standpunkt aus betrachtet gibt es keinen Unterschied zwischen den Beispielen zu poly2 und poly1. 48

49 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Java-Schnittstellen und Polymorphie Es gibt jedoch einen wichtigen Unterschied in der Implementierung: –In poly1(Base) werden durch die Base-Derived-Derived2 - Klassenvererbungskette die benötigten Subtyp-Relationen etabliert, und das Überschreiben von Methoden führt zu den korrekten Abbildungen auf Implementierungscode. –In poly2(IType) tritt ein völlig anderes Verhalten auf. Die Klassen Derived2 und Separate teilen sich keine gemeinsame Implementierungshierarchie Aber: Instanzen dieser Klassen stellen polymorphes Verhalten durch eine IType -Referenz an. 49 Durch die Gruppierung von Objekten aus unterschiedlichen Implementierungshierarchien erlauben Java-Schnittstellen polymorphes Verhalten sogar in Abwesenheit gemeinsamer Implementierungen oder überschriebener Methoden.

50 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Schnittstelle und Typ eines Objekts Was meinen wir mit der Schnittstelle eines Objekts? Typischerweise bezeichnet das die Menge aller öffentlichen Methoden, die in der Klassenhierarchie des Objekts definiert werden: –Die Menge aller öffentlich verfügbaren Methoden, die auf dem Objekt aufgerufen werden können. 50 Auf dem Bild bezieht sich die Schnittstelle zum Objekt auf die mit "Derived2 Object bezeichnete Ebene, die alle verfügbaren Methoden für das Derived2 -Objekt anführt.

51 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Schnittstelle und Typ eines Objekts Diese Definition der Objektschnittstelle führt zu einer Implementierungs-zentrischen Sichtweise –Man konzentriert sich auf die Laufzeitfähigkeiten eines Objekts, statt auf eine Typ-orientierte Sichtweise Um Polymorphie zu verstehen, müssen wir das Objekt jedoch vom typorientierten Standpunkt der mit "Base Reference" bezeichneten Ebene betrachten. Der Typ der Referenzvariablen diktiert dem Objekt eine Schnittstelle. Eine Schnittstelle, nicht die Schnittstelle. –Gelenkt von Typkonformität, können mehrere typorientierte Sichtweisen an ein Objekt gebunden werden. –Es gibt keine einzeln spezifizierte Schnittstelle zu einem Objekt. 51

52 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Schnittstelle und Typ eines Objekts Im Sinne von Typen ist die Schnittstelle zu einem Objekt die breitestmögliche Typ-orientierte Sicht darauf. –Eine an das Objekt gebundene Supertypreferenz schränkt diese Sicht typischerweise ein. Das Typkonzept erfasst den Geist der Befreiung der Objektinteraktionen von Implementierungsdetails am besten. –Anstatt sich auf die Schnittstelle eines Objekts zu beziehen, ermutigt eine typorientierte Perspektive dazu, sich auf den an das Objekt gebundenen Referenztyp zu beziehen. –Der Referenztyp diktiert die erlaubte Interaktion mit dem Objekt. Denken Sie an den Typ, wenn Sie wissen wollen, was ein Objekt tun kann, im Gegensatz zu der Art und Weise, wie das Objekt es tut. 52

53 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Objektschnittstelle (nochmals) Auf Folie 30 haben sowohl das Derived2 - als auch das Separate -Objekt eine Methode m1(). –Wie soeben diskutiert, hat die Schnittstelle beider Objekte eine Methode m1(). Es gibt jedoch mit diesen beiden Objekten keine Möglichkeit, die Methode m1() polymorph zu nutzen. –Es reicht nicht aus, dass jedes Objekt m1() hat. –Ein gemeinsamer Typ mit der Operation m1() muss existieren, durch den man die Objekte sehen kann. Die Objekte sehen so aus, als würden sie sich m1() in ihren Schnittstellen teilen. –Ohne einen gemeinsamen Supertyp ist Polymorphie in einer statisch getypten Sprache wie Java unmöglich. Der Grund ist, dass Subtyping in Java nicht strukturell sondern nominell definiert ist –Strukturell : passen die Methodensignaturen? –Nominell: es muss zusätzlich eine explizite Subtypdeklaration ( implements/extends Klausel) geben 53

54 Dr. G. Rößling Prof. Dr. M. Mühlhäuser RBG / Telekooperation © Grundlagen der Informatik I: T17 Schlussbemerkungen Das Verständnis von Subtyp-Polymorphie erfordert einen Wechsel im Denken hin zu Typen statt Implementierungen. –Typen definieren Objektgruppierungen und kontrollieren erlaubte Objektinteraktionen. –Die hierarchische Struktur von Typvererbung ergibt die zum Erreichen polymorphen Verhaltens nötigen Typbeziehungen. –Typen geben an, welche Methoden ein Objekt ausführen kann; Implementierung gibt an, wie ein Objekt auf Methodenaufrufe reagiert. –Also bestimmen Typen Verantwortlichkeiten, und Klassen implementieren sie. Durch eine saubere Trennung von Typ und Implementierung ergibt sich, dass die beiden einen "Tanz der Objekte" kontrollieren: Typen bestimmen erlaubte Tanzpartner, und Implementierungen die Choreographie der Tanzschritte. 54


Herunterladen ppt "Telecooperation/RBG Technische Universität Darmstadt Copyrighted material; for TUD student use only Grundlagen der Informatik I Thema 17: Statische Typisierung."

Ähnliche Präsentationen


Google-Anzeigen