Wiederholung Universität Paderborn Prof. Dr. Heike Wehrheim Interface (Schnittstelle) in Java: benannte Menge von Methodenspezifikationen ohne deren Implementierung Definition durch interface Sprechend { // Methodenköpfe } Ein Interface definiert eine Rolle von Objekten / Sicht auf Objekte Ein Interface legt einen Vertrag fest. GP1 WS 08/09 678 Andere Klassen können … Universität Paderborn Prof. Dr. Heike Wehrheim das Interface implementieren legen fest, wie sie die Methoden implementieren wie ihre Objekte diese Rolle einnehmen verpflichten sich dadurch zur Einhaltung des Vertrags class Bla implements Sprechend { // Methodenimplementierungen } das Interface benutzen können von der Einhaltung des Vertrags durch implementierende Klassen ausgehen benutzen Methoden des Interface ohne deren Implementierung zu kennen GP1 WS 08/09 679 Interface Namen … Universität Paderborn Prof. Dr. Heike Wehrheim können als Typen für Variablen auftreten Sprechend hugo; ihnen können Objekte der implementierenden Klassen zugewiesen werden hugo = new Bla(); GP1 WS 08/09 680 Mehrfachimplementierung Universität Paderborn Prof. Dr. Heike Wehrheim Interfaces: gleicher Methodenname, unterschiedliche Signatur interface Tierisch { interface Laufend{ void laufe(); void laufe (int km); } } Implementierende Klasse: public class Hund implements Laufend, Tierisch { public void laufe() { System.out.println("Ich laufe langsam."); } public void laufe(int km) { System.out.println("Ich laufe " + km + " Stundenkilometer schnell."); }} GP1 WS 08/09 681 Benutzende Klasse Universität Paderborn Prof. Dr. Heike Wehrheim class Hundebesitzer { public static void main (String [] args) { Hund bello = new Hund(); bello.laufe(); bello.laufe(10); } } Hundebesitzer.java GP1 WS 08/09 682 Universität Paderborn Prof. Dr. Heike Wehrheim Was passiert bei … interface Tierisch { void laufe(); } interface Laufend { void laufe (int km); } Laufend bello = new Hund(); bello.laufe(); // ????? Laufend bello = new Laufend(); bello.laufe(5); // ????? Laufend bello = new Hund(); ((Hund) bello).laufe(); // ????? Laufend bello = new Hund(); ((Tierisch) bello).laufe(); // ????? GP1 WS 08/09 683 Weitere Beispiele Universität Paderborn Prof. Dr. Heike Wehrheim 1. Zugriff auf Objekte mit Schlüsselwerten TelefonListe.java Die Schnittstelle beschreibt die Eigenschaft, daß ein Objekt aus seinen internen Daten einen Schlüsselwert vom Typ String bestimmt; dies implementiert die Funktion String getKey(). interface HasKey { String getKey(); // gib den Schlüsselwert für einen // Datensatz zurück } danach kann man z.B. sortieren oder suchen GP1 WS 08/09 684 Implementierende Klasse Universität Paderborn Prof. Dr. Heike Wehrheim Die Klasse Telefon beschreibt Objekte, die das Geforderte können: class Telefon implements HasKey { String name; int telefonnr; Telefon( String n , int tel ) { name=n ; telefonnr=tel ; } public String getKey() { return name ; } public String toString() { return "( "+name+" : "+telefonnr+" )"; } } GP1 WS 08/09 685 Benutzung Universität Paderborn Prof. Dr. Heike Wehrheim Telefon wird benutzt, um ein Telefonbuch als Array von Telefon-Objekten anzulegen: public static void main( String[] args ) { Telefon [] telefonbuch = { new Telefon( "Peter" , 12345 ) , new Telefon( "Anna" , 23753 ) , new Telefon( "Anton" , 12314 ) , new Telefon( "Monika", 44117 ) } ; Jedes Telefon-Objekt ist ein spezielles HasKey-Objekt ⇒ ein Telefon []-Objekt ist ein spezielles HasKey []-Objekt ⇒ wir können eine Methode, die ein HasKey []-Objekt sortiert, benutzen, um telefonbuch zu sortieren sort(telefonbuch) ; // sortiert Telefonbuch nach Namen static void sort( HasKey[] arr ) { ... } GP1 WS 08/09 686 Implementierung von sort Universität Paderborn Prof. Dr. Heike Wehrheim Verwendet nur die „getKey-Eigenschaft“ von HasKey-Objekten static void sort( HasKey[] arr ) { int left , min , test ; for ( left=0; left < arr.length-1; left++) { min = left; for(test = left+1;test < arr.length;test++){ if (arr[test].getKey().compareTo( arr[min].getKey() ) < 0) min = test; } tausche(arr,min,left); }} static void tausche( HasKey[] arr, int l, int m) { HasKey hilf = arr[l]; arr[l] = arr[m]; arr[m] = hilf; } GP1 WS 08/09 687 2. Beispiel Universität Paderborn Prof. Dr. Heike Wehrheim Interface für Sortierfunktionen Ziel: Sortierfunktionen unabhängig von dem Elementtyp formulieren Voraussetzung: Es gibt eine Ordnungsfunktion lessThan für den Elementtyp. Sortieralgorithmus nutzt ausschließlich diese Eigenschaft der zu sortierenden Objekte. interface Sortable { boolean lessThan (Sortable a); } die zu sortierenden Objekte müssen von Klassen stammen, die Sortable implementieren GP1 WS 08/09 688 Sortiermethode Universität Paderborn Prof. Dr. Heike Wehrheim Nimmt nur an, das Parameter ein Array von „sortierbaren“ Objekten ist static void selectSort (Sortable [] arr) { for (int left = 0;left < arr.length-1; left++) { int min = left; for (int j = left+1; j < arr.length; j++) if (arr[j].lessThan (arr[min])) min = j; // left und min tauschen Sortable tmp = arr[min]; arr[min] = arr[left]; arr[left] = tmp; } } GP1 WS 08/09 689 Verwendung Für die Klasse Telefon: Universität Paderborn Prof. Dr. Heike Wehrheim Telefonliste2.java class Telefon implements Sortable { int telefonnr; String name; ... // Konstruktor, Methoden public boolean lessThan (Sortable a) { return name.compareTo(((Telefon)a ).name )<0; } } ... Telefon [] telefonbuch; selectSort(telefonbuch); ... ergibt Sortierung nach dem Namen GP1 WS 08/09 690 Ändern der Sortierungsart Universität Paderborn Prof. Dr. Heike Wehrheim Sortierung nach Telefonnummern durch Austausch der „lessThan“-Methode: public boolean lessThan(Sortable a) { return telefonnr < ( (Telefon) a).telefonnr; } Änderung in der Klasse Telefon! Klasse Telefonliste weiß davon nichts und muß auch davon nichts wissen Telefonliste geht davon aus, daß der im Interface Sortable festgelegte „Vertrag“ (= es gibt eine Methode lessThan mit der angegeben Signatur) eingehalten wird und das bleibt auch bei Änderung der Implementierung bestehen GP1 WS 08/09 691 Was darf man, was nicht? Universität Paderborn Prof. Dr. Heike Wehrheim Schnittstellen spezifizieren Methoden mit Signaturen, geben aber nie Implementierungen an die Methoden der Interfaces sind immer public, auch wenn man es nicht hinschreibt Interfaces spezifizieren keine Konstruktoren es werden nie Objekte von Interfaces erzeugt; new Tierisch(); geht nicht! Interfaces definieren keine Variablen (Ausnahme: static final Variablen) Interfaces definieren keine static Methoden GP1 WS 08/09 692 Ein Interface aus java.util Universität Paderborn Prof. Dr. Heike Wehrheim Iterator<E> Schnittstelle spezifiziert Methoden zur Aufzählung der Elemente einer Datenstruktur (zur Iterierung über die Elemente) Der Typ der Elemente ist über E wählbar (generisches Interface), d.h. das Interface ist parametrisiert im Typ der aufzuzählenden Elemente Die implementierenden Klassen von Iterator geben an, wie die Elemente aufgezählt werden können Die aufzuzählende Struktur (Klasse für die Datenstruktur) muss eine Methode haben, um ein „passendes“ Iterator-Objekt (das weiß, wie aufgezählt werden soll) zu erzeugen. (d.h., nicht die Datenstruktur/Klasse selber implementiert das Interface, sondern sie kann Objekte einer Iteratorimplementierenden Klasse zurückliefern) GP1 WS 08/09 693 Iterator Universität Paderborn Prof. Dr. Heike Wehrheim Iterator<E> ist ein in java.util vordefiniertes Interface: public interface Iterator<E> { boolean hasNext(); E next(); void remove(); } E ist ein Platzhalter für den Typ der Elemente, hier können nachher beliebige Referenztypen eingebaut werden GP1 WS 08/09 694 Methoden von Iteratoren Universität Paderborn Prof. Dr. Heike Wehrheim Ein Iterator-Objekt e erzeugt die Aufzählung mit zwei Methoden: e.hasNext() liefert true, wenn e noch nicht alle Elemente durchlaufen hat e.next() liefert das nächste Element (remove löscht das zuletzt von next gelieferte Element) GP1 WS 08/09 695 Universität Paderborn Prof. Dr. Heike Wehrheim Anschaulich Bewegung eines Iterators Element Element next next Element Element Element next next next Iterator hasNext: true GP1 WS 08/09 true true true true false 696 Beispiel: Scanner Universität Paderborn Prof. Dr. Heike Wehrheim Scanner ist eine Iterator implementierende Klasse, und zwar für Iterator<String>: boolean hasNext(); String next(); void remove(); GP1 WS 08/09 697 Anwendungsbeispiel Universität Paderborn Prof. Dr. Heike Wehrheim Iterieren durch die Eingabe Scanner sc = new Scanner(System.in); while (sc.hasNext()) System.out.println(sc.next()); Gib alles aus, was über das Terminal eingegeben wird (Ende bspw. mit Ctrl-C.) GP1 WS 08/09 698 Beispiel: ArrayList Universität Paderborn Prof. Dr. Heike Wehrheim Datenstruktur ArrayList Speicherung von Werten in einer bestimmten Ordnung (ähnlich Arrays, aber flexibel in der Länge) ArrayList ist eine Klasse, die ein Objekt vom Typ Iterator liefern kann, dieses kann zur Aufzählung benutzt werden (ArrayList und Iterator sind Teil des sogenannten Collection-Frameworks; falls Zeit, später mehr) GP1 WS 08/09 699 ArrayList Universität Paderborn Prof. Dr. Heike Wehrheim Array-ähnliche Datenstruktur, die aber selber „mitwächst“ Anfangskapazität wird angegeben; wird diese überschritten, wird automatisch ein neues, größeres Array erzeugt Wie HashMap generische Klasse, der Typ der Elemente muss angegeben werden: ArrayList<E> (Ein) Konstruktor: ArrayList(int initialCapacity) (Einige) Methoden: E get(int index) E remove(int index) boolean add(E element) E set(int index, E element) int size() Funktionalität siehe API GP1 WS 08/09 700 Benutzung Universität Paderborn Prof. Dr. Heike Wehrheim // Anfangskapazität 10 ArrayList<Integer> arr = new ArrayList<Integer>(10); // 20 Elemente einfügen for(int i = 0; i < 20; i++) arr.add(i,i); 20 Elemente einfügen funktioniert, obwohl anfangs nur für 10 deklariert! Aus Effizienzgründen (Zeit, Platz) versuchen, die Anfangskapazität passend zu wählen. GP1 WS 08/09 701 ArrayList und Iterator Universität Paderborn Prof. Dr. Heike Wehrheim ArrayList<E> hat Methode Iterator<E> iterator() Damit kann man an ein Iterator-Objekt zu einem ArrayList-Objekt kommen; dieses kann zur Aufzählung benutzt werden Iterator<Integer> e = arr.iterator(); while (e.hasNext()) System.out.println(e.next()); ALTest.java GP1 WS 08/09 702 Eigene Iteratoren Universität Paderborn Prof. Dr. Heike Wehrheim Man kann auch selber eine Klasse schreiben, die das Interface Iterator implementiert. Wofür kann das gut sein? Haben eigene Datenstruktur zum Speichern von Elementen geschrieben, nun möchten wir einen Iterator dafür haben. Wollen einen speziellen Iterator haben, der eine bestimmte Art der Aufzählung macht. (Folgendes Beispiel aus Arnold, Gosling, Holmes: The Java Programming Language) GP1 WS 08/09 703 Anwendungsbeispiel Universität Paderborn Prof. Dr. Heike Wehrheim Beispiel: ShortStringIterator Ziel: Ein Iterator für Folgen von Zeichenketten schreiben, der nur Zeichenketten bis zu einer bestimmten Länge ausgibt (also ein Iterator, der gleichzeitig filtert). Dieser Iterator benutzt einen anderen Iterator (im folgenden Ursprungsiterator genannt), der alle Elemente aufzählt. Aus dieser Aufzählung werden dann die entsprechenden Zeichenketten herausgefiltert. Basisidee: um an das nächste Element zu kommen, wird solange ein Element aus der Ursprungsiteration erzeugt, bis diese entweder leer ist oder eine „kurze“ Zeichenkette gefunden wurde. GP1 WS 08/09 704 ShortStringIterator Universität Paderborn Prof. Dr. Heike Wehrheim Objektvariablen: Iterator<String> it der zu benutzende Ursprungsiterator String nextShort Variable zur Speicherung des nächsten Strings; null, falls keiner gefunden wurde int maxLen Maximal zulässige Länge der herauszufilternden Zeichenketten Objektmethoden: (diese fordert Interface Iterator) (Konstruktor) hasNext() next() remove() GP1 WS 08/09 705 Universität Paderborn Prof. Dr. Heike Wehrheim In Java public class ShortStringIterator implements Iterator<String> { private Iterator<String> it; private String nextShort; private final int maxLen; Ursprungsiterator public ShortStringIterator( Iterator<String> it, int maxLen) { this.it = it; this.maxLen = maxLen; nextShort = null; } nextShort am Anfang null: noch nichts gefunden GP1 WS 08/09 706 … Universität Paderborn Prof. Dr. Heike Wehrheim public boolean hasNext() { Nach nächstem kurzen if (nextShort != null) return true; String suchen while (it.hasNext()) { nextShort = it.next(); if (nextShort.length() <= maxLen) return true; } Gefunden? Dann nextShort = null; fertig! return false; } Achtung: Nebeneffekt! public String next() { if (nextShort == null && ! hasNext()) throw new NoSuchElementException(); String n = nextShort; Exception werfen, wenn next nextShort = null; aufgerufen wird, obwohl kein return n; nächstes Element existiert } GP1 WS 08/09 707 … Universität Paderborn Prof. Dr. Heike Wehrheim public void remove() { throw new UnsupportedOperationException(); } Konvention des Collection Frameworks: nicht unterstützte Methoden werfen UnsupportedOperationException ShortStringIterator.java GP1 WS 08/09 708 Benutzung davon Universität Paderborn Prof. Dr. Heike Wehrheim Zwei Beispiele: a) der Ursprungsiterator ist ein Scanner und b) der Ursprungsiterator ist der Iterator einer ArrayList Scanner sc = new Scanner("Dies ist eine Zeichenkette mit langen und mit kuerzeren Worten …“); ShortStringIterator it = new ShortStringIterator(sc,6); while (it.hasNext()) System.out.print( it.next() + " "); ArrayList<String> arr = new ArrayList<String>(10); // arr füllen ShortStringIterator it2 = new ShortStringIterator(arr.iterator(),6); while (it2.hasNext() ) System.out.print( it2.next() + " "); ShortStringApplication.java GP1 WS 08/09 709 Zusammenfassung Universität Paderborn Prof. Dr. Heike Wehrheim Interface (Schnittstelle) in Java: Eine benannte Menge von Methodenspezifikationen - ohne deren Implementierung: interface Movable { boolean start (); void stop (); boolean turn (int degrees); } Interfaces spezifizieren bestimmte Sichten/Rollen Interfaces legen Verträge fest (Methodensignaturen), die die implementierenden Klassen einhalten müssen GP1 WS 08/09 710 In Klassen Universität Paderborn Prof. Dr. Heike Wehrheim Klassen können bestimmte, hinter implements aufgeführte Interfaces implementieren (auch mehrere): class Bike implements Movable { public boolean start () {...} // Implementierung von stop und turn sowie // weiterer Methoden ... } class Car implements Movable, Motorized { // Implementierung der Methoden aus Movable // und Motorized, sowie weiterer ... } damit können ihre Objekte die in den Interfaces festgelegten Rollen einnehmen mit der Implementierung „sagt“ die Klasse, daß sie den Vertrag der Schnittstelle einhält GP1 WS 08/09 711 Interface als Typabstraktion Universität Paderborn Prof. Dr. Heike Wehrheim Interfaces werden als Typabstraktion verwendet (Typ von Variablen): Movable vehicle; ... vehicle = new Bike(); ... vehicle.turn(20);... Typische Anwendung: Spezifikation von Eigenschaften (Movable) oder Rollen, damit Algorithmen möglichst allgemein formuliert werden können: void drive (Movable vehicle, Coordinate from, Coordinate to) { vehicle.start (); vehicle.turn (45); vehicle.stop (); ... } GP1 WS 08/09 712