TU Kaiserslautern Prof. Dr. A. Poetzsch-Heffter M. Weber, M. Sc. Fachbereich Informatik P. Zeller, M. Sc. AG Softwaretechnik Übungsblatt 13: Software-Entwicklung 1 (WS 2013/14) Ausgabe: in der Woche vom 27.01.14 bis zum 31.01.14 Abgabe: in der Woche vom 03.02.14 bis zum 07.02.14 Abnahme: max. zwei Tage nach der Übung Aufgabe 1 Mensapläne in Java (Präsenzaufgabe) Wir betrachten noch einmal die Datentypdefinition für die Mensapläne von Übungsblatt 5. data Tag = MO | DI | MI | DO | FR data Ausgabe = Essen1 | Essen2 | Grill | Wok data Angebot = Angebot Tag Ausgabe String deriving (Eq , Ord , Show) deriving (Eq , Ord , Show) deriving (Eq , Ord , Show) type Mensaplan = [ Angebot ] a) Implementieren Sie eine Interface- und Klassenhierarchie für den Datentyp Mensaplan. b) Erweitern Sie die Klasse Mensaplan um eine Methode Mensaplan suche(String text), die zu einem Suchtext einen gefilterten Plan zurückgibt, der nur noch Angebote beinhaltet, die den Suchtext enthalten. Hinweis: Sie können die Methode contains auf einem String verwenden, um zu testen, ob ein String in einem anderen enthalten ist: Bsp. titel.contains(text) Aufgabe 2 Mensapläne in Java (Einreichaufgabe) Für Haskell-Mensapläne werden durch die Typklassen Show und Eq Funktionen zum Vergleich zweier Mensapläne und zur Umwandlung in einen String bereit gestellt. Diese Funktionalität wird in dieser Aufgabe auch für Java-Mensapläne implementiert. a) Jedes Java-Objekt besitzt die Methode toString() die eine Stringdarstellung des Objektes liefert. Diese Methode ist in der Klasse Object1 implementiert. Überschreiben Sie die Methode String toString() in den von Ihnen implementierten Klassen, so dass, IO.println(mensaplan) für einen Mensaplan eine lesbare Ausgabe erzeugt. b) Um Objekte zu vergleichen, besitzt jedes Objekt die Methode boolean equals(Object o) verwendet. Die Implemtierung in der Klasse Object vergleicht die Referenzen der Objekte nicht jedoch die Inhalte. Überschreiben Sie die Methode equals(Object o) in den von Ihnen implementierten Klassen, so dass, ein Vergleich zweier Mensapläne mit equals das gleiche Ergebnis liefert wie ein Vergleich entsprechender Pläne mit (==) in Haskell. Hinweis: Beachten Sie die Typsignatur von equals. Casten Sie in Ihrer Implementierung den Parameter auf den gewünschten Typ und liefern Sie false als Ergebnis, wenn dies nicht möglich ist. 1 Jede Klasse erbt direkt oder indirekt von der Klasse Object. Aufgabe 3 Dynamisches Binden (Präsenzaufgabe) Betrachten Sie folgendes Programm. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 interface I1 { public char mi (A a); } interface I2 extends I1 { public char mii (I2 a); } interface A { public char m(); } interface B extends A, I1 { public char n(A a); } 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class E implements A { public char m() { return ’E’; }; public char n(A a) { return a.m(); }; public void o(I1 i) { ... }; public static void main ( String [] args) { A a1 = new E(); A a2 = new C(); char char char char r1 r2 r3 r4 = = = = a1.m(); a2.m(); ((E) a1).n(a2); ((B) a2).m(); } } class C implements B, I2 { public char m() { return ’C’; }; public void o(I1 i) { ... }; ... } a) Welche Methoden müssen die Klassen C und E implementieren? b) Von welchem Typ können s und t in den folgenden Ausdrücken sein? new E().n(s) new C().o(t) c) Welchen Wert enthalten die Variablen r1 bis r4 nach der Ausführung von Zeile 35? Aufgabe 4 Java Collection Klassen (Einreichaufgabe) Neben den eigentlichen Sprachfeatures zeichnet sich Java durch eine gut ausgestattete Standardbibliothek aus, welche durch eine Vielzahl von Klassen und Schnittstellen Implementierungen vereinfacht, indem auf die zur Verfügung gestellten Bausteine mittels Vererbung, Subtyping usw. zurückgegriffen werden kann. Die im Paket java.util angesiedelten Collection-Klassen stellen unter anderem Implementierungen für im Programmieralltag häufig auftretende Datenstrukturen bereit. Die Dokumentation zu diesem und den anderen Bestandteilen des aktuellen JDKs ist unter http://java.sun.com/javase/7/docs/api verfügbar. Eine Übersicht des Collection Frameworks finden Sie unter http://docs.oracle.com/javase/7/ docs/technotes/guides/collections/reference.html. a) Erstellen sie ein Diagramm, welches die Subtyp-Beziehungen zwischen den Typen Iterable, Collection, List, LinkedList, ArrayList, Map, HashMap, LinkedHashMap, TreeMap, Set, HashSet, LinkedHashSet und TreeSet darstellt. b) Betrachten Sie die Klasse HashSet. Wo ist die Implementierung der Methode containsAll zu finden? Hinweis: Auf der Seite http://grepcode.com/ findet man (unter anderem) den Code der Java Standardbibliothek (in “JDK” bzw. “openjdk”). c) Schreiben Sie eine Funktion findDuplicates, welche eine Liste von Strings nimmt und nach Strings sucht, die mehrmals in der Liste vorkommen. Rückgabewert der Funktion soll eine Collection sein, welche alle Wörter enthält, die mehr als einmal in der gegebenen Liste vorkommen. Verwenden Sie ein HashSet um die Funktion zu implementieren. d) Schreiben Sie eine Funktion countWords, welches eine Liste von Strings nimmt und für jedes Wort in der Liste zählt, wie oft es in der Liste vorkommt. Das Ergebnis soll als Map<String,Integer> zurückgegeben werden. Wenn zum Beispiel das Wort "blub" 3 mal in der Liste list vorkommt, dann soll gelten, dass count(list).get("blub") == 3. e) Zusatzaufgabe: Schreiben Sie eine Funktion, die eine Liste von Klausur-Ergebnissen nimmt und diese sortiert. Die Liste soll so sortiert sein, dass die höchsten Punktzahlen zuerst kommen. Bei gleicher Punktzahl sollen die Ergebnisse alphabetisch nach dem Namen sortiert sein. Verwenden Sie die sort-Methode aus der Klasse Collections, die eine Liste und einen Comparator verwendet. Ein Klausur-Ergebnissen ist definiert durch die folgende Klasse: class KlausurErgebnis { int punkte ; String name; } Hinweis: Definieren Sie sich eine geeignete Comparator-Klasse. Um Strings miteinander zu vergleichen können Sie die compareTo-Methode auf Strings verwenden. Aufgabe 5 Dynamisches Binden und Casts (Einreichaufgabe) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 interface I { String getS (); } class A { void print( String s) { System .out. println (s); } String name () { return "A"; } void printName () { print(name ()); } void m(I x) { print(x.getS ()); } } class B extends A implements I { String name () { return "B"; } public String getS () { return "SB"; } } class C extends A { void printName () { print(name ()+"?"); } String name () { return "C"; } public String getS () { return "SC"; } void m(C c) { print(c.name ()+"!"); } } class D extends B { String name () { return "D"; } } 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 public class Test { public static void main( String [] a) { A x1 = new D(); A x2 = new E(); C x3 = new E(); B x4 = new B(); A x5 = new C(); x2.print(x1.name ()); x1.print(x2.name ()); x1. printName (); x2. printName (); x3.m(x3); x3.m(x4); x3.m((I) x3); x1.print(z(x3)); x1.print(z(x5)); } static String z(A a) { String r = a.name (); if (a instanceof I) r += ((I) a).getS (); if (a instanceof C) r += ((C) a).getS (); return r; } } class E extends C implements I { String name () { return "E"; } public String getS () { return "SE"; } } Welche Ausgabe wird durch das Programm erzeugt? Begründen Sie das Ergebnis für jede Ausgabe-Zeile kurz. Aufgabe 6 Vorlesungsumfrage Wir sind an Ihrer Meinung zur Vorlesung und zu den Übungen interessiert und bitten Sie daher an der Vorlesungsumfrage teilzunehmen. Aufgabe 7 Objektorientierte Syntaxbäume (Präsenzaufgabe) In der Vorlesung haben wir bereits gesehen, wie wir Syntaxbäume der Programmiersprache Femto in Haskell darstellen können. Dazu haben wir Datentypen gesehen, die einen Ausdruck, eine Wertdekl und ein Programm darstellen (vergleiche Femto.hs auf der Materialienseite). Syntaxbäume können jedoch auch mit Hilfe von objektorientierten Hilfsmitteln dargestellt werden. Ein gemeinsamer Supertyp repräsentiert dabei einen Ausdruck im allgemeinen und für jede Art von Ausdruck existiert eine Klasse, die Subtyp von Ausdruck ist. a) Implementieren Sie das Interface Ausdruck sowie die Klasse Add, die die Addition zweier Ausdrücke in Femto repräsentiert. b) Fügen Sie der Implementierung eine Methode print hinzu, welche Ausdrücke auf die Konsole ausgibt. Aufgabe 8 Objektorientierte Syntaxbäume (Einreichaufgabe) In Aufgabe 7 haben Sie in der Präsenzübung bereits angefangen, Klassen für die objektorientierte Repräsentation eines Femto Programms zu implementieren. a) Implementieren Sie die restlichen Klassen zur Darstellung eines Femto-Syntaxbaums inklusive der Möglichkeit der Ausgabe des Syntaxbaums als Femto Programm. Hinweis: Für Deklaration und Programm, welche keine Ausdrücke darstellen, sollen eigene Klassen verwendet werden, sie sollen jedoch ebenfalls ausgegeben werden können. b) Laden Sie sich die Datei Environment.java von der Materialienseite herunter. Sie enthält eine Implementierung eines Environments zur Auswertung von Femto Ausdrücken. Fügen Sie ihrer Implementierung eine Methode eval hinzu, welche das Femto-Programm auswertet. Dabei werden die Ausdrücke zu einem int ausgewertet, bei der Auswertung des Programms soll das Ergebnis des Programms auf die Konsole ausgeben werden. c) Wir wollen nun eine alternative Lösung in Java entwickeln, die es erlaubt, elegant neue Methoden zu definieren, ohne die unterschiedlichen Klassen ( Zahl, Bzn, Add, ...) anzupassen. Wir wollen dazu das Entwurfsmuster Visitor verwenden. Über das Entwurfsmuster können Sie sich z. B. auf Wikipedia (http://de.wikipedia.org/wiki/Visitor) informieren. interface Ausdruck { void accept ( ExprVisitor v); } class Zahl implements Expr { int i; public void accept ( ExprVisitor v) { v. visit(this); } } class Bzn ... class Add ... class Mult ... interface ExprVisitor { void visit(Zahl z); void visit(Bzn bzn); void visit(Add a); void visit(Mult m); } class EvalExpr implements ExprVisitor { int i = 0; Environment e = new Environment (); EvalExpr ( Environment env) { this.e = env; } public void visit(Zahl z) {.. .} public void visit(Bzn bzn) {.. .} public void visit(Add a) {.. .} public void visit(Mult m) {.. .} } Passen sie die Implementierung der Klassen entsprechend an und Implementieren Sie einen Visitor, der Femto-Ausdrücke auswertet und einen Visitor, der Femto-Programme auswertet und ihr Ergebnis auf die Konsole ausgibt.