Programmieren in Java

Ähnliche Dokumente
Java Einführung Abstrakte Klassen und Interfaces

Programmieren in Java

Übung 1 mit C# 6.0 MATTHIAS RONCORONI

Objektorientierte Programmierung. Kapitel 12: Interfaces

Java Schulung (Java 2 Java Development Kit 5 / 6)

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {...

1 Polymorphie (Vielgestaltigkeit)

Objektorientierte Programmierung

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 14/15. Kapitel 11. Fehler und Ausnahmen 1

Type Erasure in Java 5. Helmi Jouini Institut für Theoretische Informatik Universität Karlsruhe

Problemstellung. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 24: Reflection 1. IDE und automatische Tests.

5.5.8 Öffentliche und private Eigenschaften

Java Kurs für Anfänger Einheit 4 Klassen und Objekte

5. Tutorium zu Programmieren

Binärbäume. Prof. Dr. E. Ehses,

Kapitel 6. Vererbung

Klassenbeziehungen & Vererbung

Vererbung & Schnittstellen in C#

Bäume. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 10: Collections 4. Inhalt. Bäume. Einführung. Bäume.

Kapitel 6. Vererbung

Probeklausur: Programmierung WS04/05

Kapitel 6. Vererbung

Algorithmen und Datenstrukturen

3 Objektorientierte Konzepte in Java

Schnittstellen implementieren am Beispiel Suchbaum

Objektorientierte Programmierung

Lösungsvorschläge. zu den Aufgaben im Kapitel 4

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

Algorithmen und Datenstrukturen 07

Grundlagen von Python

Innere Klassen in Java

Musterlösung zur Vorlesung Modellbasierte Softwareentwicklung Wintersemester 2014/2015 Übungsblatt 9

Software Engineering Klassendiagramme Einführung

Große Übung Praktische Informatik 1

Quellcode-Repräsentation in Eclipse. Seminarvortrag PG Reclipse Jan Rieke

Themen. Web Service - Clients. Kommunikation zw. Web Services

Musterlösungen zur Klausur Informatik 3

Programmierkurs Java

Design Patterns 2. Model-View-Controller in der Praxis

Typumwandlungen bei Referenztypen

Javakurs 2013 Objektorientierung

Prinzipien Objektorientierter Programmierung

2.4.3 Polymorphie (Wiederholung von Alp2)

Drei-Schichten-Architektur. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 16: 3-Schichten-Architektur 1 Fachkonzept - GUI

II.1.1. Erste Schritte - 1 -

Generische Datenstrukturen

Übersicht. Informatik 2 Teil 3 Anwendungsbeispiel für objektorientierte Programmierung

Abschnitt 9: Schnittstellen: Interfaces

7. Objektorientierte Softwareentwicklung/3. Informatik II für Verkehrsingenieure

3 Objektorientierte Konzepte in Java

12) Generische Datenstrukturen

5. Abstrakte Klassen. Beispiel (3) Abstrakte Klasse. Beispiel (2) Angenommen, wir wollen die folgende Klassenhierarchie implementieren:

5.6 Vererbung. Vererbung

Institut fu r Informatik

Vorlesung 09: Mengen. Peter Thiemann SS 2010

Versuchsziele Kenntnisse in der Anwendung von: Sortieren mit Klassen Benutzung von generischen Klassen o Definition o Sortierung.

Java Kurs für Anfänger Einheit 5 Methoden

Betreutes Programmieren Vorlesung Informatik II, Blatt 7 Musterlösung

Java Einführung Methoden in Klassen

Einführung in die objektorientierte Programmierung mit Java. Klausur am 19. Oktober 2005

EINI WiMa/LW. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 11/12

Java für Computerlinguisten

13. Tutorium zu Programmieren

Test zu Grundlagen der Programmierung Leitung: Michael Hahsler. 21. November 2003

Variablen manipulieren per JDI

Java Einführung VARIABLEN und DATENTYPEN Kapitel 2

Eine Klasse beschreibt Objekte mit gleichen Attributen und Methoden.

Aufgabenblatt Nr. 5 Generizität und TicTacToe

5. Abstrakte Klassen

Javakurs für Anfänger

5.4 Klassen und Objekte

Repetitorium Informatik (Java)

Programmieren I. Strategie zum Entwurf von Klassen. Beispiele. Design von Klassen. Dr. Klaus Höppner. Beispiel: Bibliothek

Java Generics & Collections

Tutorium 5 - Programmieren

Java-Programmierung. Remote Method Invocation - RMI

C++ - Operatoren. Eigene Klassen mit neuen Funktionen

Programmierkurs Java

Software-Entwurfsmuster

12) Generische Datenstrukturen

1. Grundzüge der Objektorientierung 2. Methoden, Unterprogramme und Parameter 3. Datenabstraktion 4. Konstruktoren 5. Vordefinierte Klassen

PIWIN I. Praktische Informatik für Wirtschaftsmathematiker, Ingenieure und Naturwissenschaftler I. Vorlesung 3 SWS WS 2007/2008

Aufgabe 1. »Programmieren«, WS 2006/2007. Nino Simunic M.A.

Objektorientiertes JavaScript

Praktikum Datenbanksysteme. Ho Ngoc Duc IFIS - Universität zu Lübeck

von Anja Austermann Drag and Drop

Prof. Dr. Uwe Schmidt. 21. August Aufgaben zur Klausur Objektorientierte Programmierung im SS 2007 (IA 252)

Interaktionen zwischen Objekten durch Senden von Nachrichten und Reagieren auf empfangene Nachrichten

Fakultät Angewandte Informatik Programmierung verteilter Systeme Übungen zur Vorlesung Informatik II, Blatt 6

Daniel Warneke Ein Vortrag im Rahmen des Proseminars Software Pioneers

Computeranwendung und Programmierung (CuP)

Einführung Datentypen Verzweigung Schleifen Funktionen Dynamische Datenstrukturen. Java Crashkurs. Kim-Manuel Klein

Client-Server-Beziehungen

Bean-Mapping mit MapStruct

Objects First With Java A Practical Introduction Using BlueJ. Mehr über Vererbung. Exploring polymorphism 1.0

Methoden. von Objekten definiert werden, Methoden,, Zugriffsmethoden und Read-Only

Transkript:

Programmieren in Java Vorlesung 06: Das Visitor Pattern Prof. Dr. Peter Thiemann (vertreten durch Luminous Fennell) Albert-Ludwigs-Universität Freiburg, Germany SS 2015 Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 1 / 25

Executive Summary Visitor Pattern Design-Pattern, dass bei rekursiven Klassen Verwendung findet Es erlaubt einfaches und modulares Hinzufügen von Operationen für ein Datenmodell Erweitern des Datenmodells ist schwieriger Gegenspieler zum Composite Pattern, wo Operationen schwerer hinzuzufügen sind. Geeignete Modelle sind z.b. Arithmetische/Boolesche/... Ausdrücke Repräsentation von Programmen einer Programmiersprache (z.b. beim Compilerbau) Operationen werden als Subklassen eines Visitor-Interfaces per Fallunterscheidung implementiert Es genügt eine Methode im Datenmodell (accept) um eine Vielzahl von Visitor-basierten Operationen zu Unterstützen Laufendes Beispiel heute: Arithmetische Ausdrücke Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 2 / 25

Inhalt Wiederholung: Arithmetische Ausdrücke Einschub: Static Imports Hinzufügen weiterer Operationen Visitors Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 3 / 25

Wiederholung: Arithmetische Ausdrücke Wiederholung: Arithmetische Ausdrücke Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 4 / 25

Wiederholung: Arithmetische Ausdrücke Arithmetische Ausdrücke Datenmodell Ein arithmetischer Ausdruck hat eine der folgenden Formen: eine Konstante (eine ganze Zahl), Beispiele: 0, 51, 42 eine Summe von zwei arithmetischen Ausdrücken, Beispiele: 3+4, 17+4, 17+ (2+2) ein Produkt von zwei arithmetischen Ausdrücken, Beispiele: 3 4, 2 (17+4), (2 3) 4 Operationen für arithmetische Ausdrücke Berechnung des Werts: eval(3 + 4) 7 Berechnung seiner Größe: size(3 + 4) 3 Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 5 / 25

Wiederholung: Arithmetische Ausdrücke Datenmodell Arithmetische Ausdrücke sind rekursive, unveränderliche Datenstrukturen Basisfall: Konstanten Rekursive Fälle: Addition und Produkt Hier: Zugriff auf Bestandteile durch public final Felder. Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 6 / 25

Wiederholung: Arithmetische Ausdrücke Operationen Modellierung mit Composite Pattern Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 7 / 25

Einschub: Static Imports Static Imports Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 8 / 25

Einschub: Static Imports Erzeugen von Beispiel-Ausdrücken Mit Java Konstruktoren 1 @Test 2 public void testeval() { 3 // (42 + (5 4)) (2 + 1) 4 IExpr e = new Product(new Add(new Const(42), new Product(new Const(5), 5 new Const(4))), new Add(new Const(2), new Const(1))); 6 assertequals(168, e.eval()); 7 } Java s Syntax für Konstruktoraufrufe ist für das Erstellen verschachtelter Strukturen sehr unleserlich. Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 9 / 25

Einschub: Static Imports Erzeugen von Beispiel-Ausdrücken Mit statischen Factory-Methoden 1 @Test 2 public void testevalstatic() { 3 // (42 + (5 4)) (2 + 1) 4 IExpr e = product(add(42, product(5, 4)), add(2, 1)); 5 assertequals(168, e.eval()); 6 } Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 10 / 25

Einschub: Static Imports Erzeugen von Beispiel-Ausdrücken Mit statischen Factory-Methoden 1 @Test 2 public void testevalstatic() { 3 // (42 + (5 4)) (2 + 1) 4 IExpr e = product(add(42, product(5, 4)), add(2, 1)); 5 assertequals(168, e.eval()); 6 } Die statischen Methoden product und add sind statische Methoden aus einer Klasse Expressions. Durch statische Imports kann der Klassenname beim Aufruf weggelassen werden import composite.expressions; normaler import, erlaubt: Expressions.add(42, 5); import static composite.expressions. ; statischer import, erlaubt: add(42,5) Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 10 / 25

Hinzufügen weiterer Operationen Hinzufügen weiterer Operationen Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 11 / 25

Hinzufügen weiterer Operationen Weitere Operationen für Arithmethische Ausdrücke prettyprint(iexpr) prettyprint(add(add(0, 5), 8)) ((0 + 5) + 8) Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 12 / 25

Hinzufügen weiterer Operationen Weitere Operationen für Arithmethische Ausdrücke prettyprint(iexpr) prettyprint(add(add(0, 5), 8)) ((0 + 5) + 8) depth(iexpr) depth(add(add(0, 5), 8)) 3 Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 12 / 25

Hinzufügen weiterer Operationen Weitere Operationen für Arithmethische Ausdrücke prettyprint(iexpr) prettyprint(add(add(0, 5), 8)) ((0 + 5) + 8) depth(iexpr) depth(add(add(0, 5), 8)) 3 simplify() simplify(add(add(0, 5), 8)) add(5, 8) Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 12 / 25

Hinzufügen weiterer Operationen Weitere Operationen für Arithmethische Ausdrücke prettyprint(iexpr) prettyprint(add(add(0, 5), 8)) ((0 + 5) + 8) depth(iexpr) depth(add(add(0, 5), 8)) 3 simplify() simplify(add(add(0, 5), 8)) add(5, 8) Bisher: Modellierung mit Composite Pattern Problem: Composite Pattern erfordert beim Hinzufügen die Modifikation aller Ausdruck-Klassen Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 12 / 25

Hinzufügen weiterer Operationen Weitere Operationen für Arithmethische Ausdrücke Modellierung mit Composite Pattern Problem: Composite pattern erfordert Modifikation aller Ausdruck-Klassen Implementierung der Operation ist über viele Klassen verteilt Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 13 / 25

Hinzufügen weiterer Operationen Operationen für Arithmethische Ausdrücke in einer idealen Welt 1 public static int eval(iexpr e) { 2 / 3 falls e eine Const Instanz ist, 4 dann return e.value 5 falls e eine Add Instanz ist, 6 dann return eval(e.left) + eval(e.right) 7 falls e eine Produkt Instanz ist, 8 dann return eval(e.left) * eval(e.right) 9 / 10 } Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 14 / 25

Hinzufügen weiterer Operationen Operationen für Arithmethische Ausdrücke in einer idealen Welt 1 public static int eval(iexpr e) { 2 / 3 falls e eine Const Instanz ist, 4 dann return e.value 5 falls e eine Add Instanz ist, 6 dann return eval(e.left) + eval(e.right) 7 falls e eine Produkt Instanz ist, 8 dann return eval(e.left) * eval(e.right) 9 / 10 } Logik der Operation gesammelt an einer Stelle Ausdruck-Klassen bleiben unangetastet Es kann im Prinzip leicht geprüft werden ob alle Fälle beachtet worden sind Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 14 / 25

Hinzufügen weiterer Operationen Keine wirkliche Lösung: instanceof 1 public static int eval(iexpr e) { 2 if (e instanceof Const) { // falls e eine Const Instanz ist 3 Const c = (Const) e; 4 return c.value; 5 } else if (e instance of Add) { // falls e eine Add Instanz ist 6 Add a = (Add) e; 7 return eval(a.left) + eval(a.right) 8 } else if (...) { //... 9... 10 } else { // Fehler, wenn kein Fall zutrifft 11 return IllegalArgumentException... 12 } 13 } Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 15 / 25

Hinzufügen weiterer Operationen Keine wirkliche Lösung: instanceof 1 public static int eval(iexpr e) { 2 if (e instanceof Const) { // falls e eine Const Instanz ist 3 Const c = (Const) e; 4 return c.value; 5 } else if (e instance of Add) { // falls e eine Add Instanz ist 6 Add a = (Add) e; 7 return eval(a.left) + eval(a.right) 8 } else if (...) { //... 9... 10 } else { // Fehler, wenn kein Fall zutrifft 11 return IllegalArgumentException... 12 } 13 } Repetitives, fehleranfälliges Muster: if(e instanceof Klasse ) { Klasse x = ( Klasse ) e;...} Laufzeitfehler wenn ein Fall vergessen wird bei falschen Casts... insbesondere wenn doch noch ein Fall nachträglich hinzugefügt wird Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 15 / 25

Visitors Visitors Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 16 / 25

Visitors Überblick Die Operationen sind Implementierungen eines Visitor-Interfaces Rückgabetyp einer Operation ist der generische Parameter T die verschiedenen Fälle sind auf die visit Methoden aufgeteilt Keine Typecasts und instanceof Test nötig Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 17 / 25

Visitors Beispiel: Eval 1 class Eval implements IExprVisitor<Integer> { 2 public Integer visitconst(const c) { 3 return c.value; 4 } 5 public Integer visitadd(add a) { 6 return / a.left + a.right /; 7 } 8 public Integer visitproduct(product p) { 9 return / p.left p.right /; 10 }}... die verschiedenen Fälle sind auf die visit Methoden aufgeteilt Keine Typecasts und instanceof Test nötig Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 18 / 25

Visitors Beispiel: Eval 1 class Eval implements IExprVisitor<Integer> { 2 public Integer visitconst(const c) { 3 return c.value; 4 } 5 public Integer visitadd(add a) { 6 return / a.left + a.right /; 7 } 8 public Integer visitproduct(product p) { 9 return / p.left p.right /; 10 }}... die verschiedenen Fälle sind auf die visit Methoden aufgeteilt Keine Typecasts und instanceof Test nötig Es bleibt zu klären: Wie wird Eval aufgerufen? Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 18 / 25

Visitors Anwenden von Visitors Das Ausdruck-Interface (IExpr) muss das Visitor-Pattern unterstützen: nur der Ausdruck selber weiß welcher Fall aufgerufen werden muss Dazu reicht eine Methode accept(iexprvisitor v),,aufruf der Operation: e.accept(new Eval()) Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 19 / 25

Visitors Anwenden von Visitors Das Ausdruck-Interface (IExpr) muss das Visitor-Pattern unterstützen: nur der Ausdruck selber weiß welcher Fall aufgerufen werden muss Dazu reicht eine Methode accept(iexprvisitor v),,aufruf der Operation: e.accept(new Eval()) Aufrufe im Vergleich Composite Pattern IExpr e = add(5, 4); Integer i = e.eval(); String s = e.prettyprint(); VisitorPattern IExpr e = add(5, 4); Integer i = e.accept(new Eval()); String s = e.accept(new PrettyPrint()); Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 19 / 25

Visitors Einschub: Generische Methoden Die Signatur von,,accept IExpr e = add(5, 4); Integer i = e.accept(new Eval()); String s = e.accept(new PrettyPrint()); Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 20 / 25

Visitors Einschub: Generische Methoden Die Signatur von,,accept IExpr e = add(5, 4); Integer i = e.accept(new Eval()); String s = e.accept(new PrettyPrint()); Die Methode accept muss zu IExpr hinzugefügt werden: interface IExpr {?? accept(iexprvisitor<??> v); } Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 20 / 25

Visitors Einschub: Generische Methoden Die Signatur von,,accept IExpr e = add(5, 4); Integer i = e.accept(new Eval()); String s = e.accept(new PrettyPrint()); Die Methode accept muss zu IExpr hinzugefügt werden: interface IExpr {?? accept(iexprvisitor<??> v); // String accept(iexprvisitor<string> v) // Integer accept(iexprvisitor<integer> v) } Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 20 / 25

Visitors Einschub: Generische Methoden Die Signatur von,,accept IExpr e = add(5, 4); Integer i = e.accept(new Eval()); String s = e.accept(new PrettyPrint()); Die Methode accept muss zu IExpr hinzugefügt werden: interface IExpr { <T> T accept(iexprvisitor<t> v); // String accept(iexprvisitor<string> v) // Integer accept(iexprvisitor<integer> v) } Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 20 / 25

Visitors Einschub: Generische Methoden Die Signatur von,,accept IExpr e = add(5, 4); Integer i = e.accept(new Eval()); String s = e.accept(new PrettyPrint()); Die Methode accept muss zu IExpr hinzugefügt werden: interface IExpr { <T> T accept(iexprvisitor<t> v); // String accept(iexprvisitor<string> v) // Integer accept(iexprvisitor<integer> v) } <T> T accept(iexprvisitor<t> v) ist eine generische Methode. anders als bei generischen Klassen (vgl. List<T>), muss der Typparameter beim Aufruf meist nicht angegeben werden. ansonsten: String s = e.<string>accept(new PrettyPrint()) Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 20 / 25

Visitors Anwenden von Visitors Das Ausdruck-Interface muss Visitor unterstützen: nur der Ausdruck selber weiß welcher Fall aufgerufen werden muss. Dazu reicht eine Methode accept(iexprvisitor v) Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 21 / 25

Visitors Beispiel: Eval 1 class Eval implements IExprVisitor<Integer> { 2 public Integer visitconst(const c) { 3 return c.value; 4 } 5 public Integer visitadd(add a) { 6 return a.left.accept(this) + a.right.accept(this); 7 } 8 public Integer visitproduct(product p) { 9 return p.left.accept(this) p.right.accept(this); 10 }}... die verschiedenen Fälle sind auf die visit Methoden aufgeteilt Keine Typecasts und instanceof Test nötig Implementierung von accept ist mechanisch. (d.h. die Methode könnte automatisch generiert werden) Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 22 / 25

Visitors Beispiel: Depth Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 23 / 25

Visitors Hinzufügen von Fällen Ein arithmetischer Ausdruck ist entweder... oder eine Variable, z.b.: new Var( x ) Das Visitor-Pattern stellt sicher, dass alle Visitor-basierten Operationen nachgebessert werden müssen Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 24 / 25

Visitors Hinzufügen von Fällen Ein arithmetischer Ausdruck ist entweder... oder eine Variable, z.b.: new Var( x ) Das Visitor-Pattern stellt sicher, dass alle Visitor-basierten Operationen nachgebessert werden müssen beim Hinzufügen von Fällen muss die accept Methode implementiert werden (Teil von IExpr) dabei fällt auf, dass ein entsprechender visit Fall fehlt der muss zum Visitor Interface hinzugefügt werden was zwangsweise eine Anpassung aller konkreten Visitors nach sich zieht Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 24 / 25

Visitors Eigenschaften des Visitor Patterns Vorteile keine Casts oder instanceof checks Die Operationen müssen alle Fälle behandeln. Nachteile Fälle hinzufügen ist aufwendig (vgl. Die Operationen müssen alle Fälle behandeln ) Peter Thiemann (Univ. Freiburg) Programmieren in Java JAVA 25 / 25