Info B VL 11: Innere Klassen/Collections Objektorientiere Programmierung in Java 2003 Ute Schmid (Vorlesung) Elmar Ludwig (Übung) FB Mathematik/Informatik, Universität Osnabrück Info B VL 11: Innere Klassen/Collections – p.254 Wiederholung: Innere Klassen Vier Arten von inneren Klassen: Member Classes (“echte” innere Klasse) Static Member Classes (Nested Top-Level Classes) Local Classes Anonymous Classes Info B VL 11: Innere Klassen/Collections – p.255 Lokale Klassen / Nachtrag public class Test { public static interface Value { public int getValue (); public void setValue (int i); } public Value[] foo () { int value = 0; class Local implements Value { public int getValue () { return value; } public void setValue (int i) { value = i; } }; return new Value[] { new Local(), new Local() }; } public static void main (String args[]) { Test test = new Test(); Value[] v = test.foo(); // two value objects v[0].setValue(42); v[1].setValue(24); System.out.println(v[0].getValue()); // ??? } } Info B VL 11: Innere Klassen/Collections – p.256 Anonyme Klassen Namenlose lokale Klassen Kombination der Syntax von Klassen-Definition und Objekt-Erzeugung wie lokale Klassen innerhalb eines Ausdrucks definiert Info B VL 11: Innere Klassen/Collections – p.257 ‘Enumerator’ als anonyme Klasse public java.util.Enumeration enumerate() { // The anonymous class is defined as part of the // return statement return new java.util.Enumeration() { protected int current = 0; public boolean hasMoreElements() { return current < numOfEls; } public Object nextElement() { if (! hasMoreElements()) throw new java.util.NoSuchElementException(); return list[current++]; } }; // semicolon required to finish return statement } Info B VL 11: Innere Klassen/Collections – p.258 Eigenschaften von Anonymen Kl. (1) Lokale Klasse ohne Namen. Definition und Instantiierung in einem einzigen Ausdruck (new Operator). ( [ argument-list ] ) class-body class-name new Zwei Formen: interface-name ( ) class-body new Konstruktoraufruf der Oberklasse (evtl. auch Default-Konstruktor), Erzeugung eines Objekts der anonymen Unterklasse. Default-Konstruktoraufruf für ein Interface, Erzeugung einer anonymen Unterklasse von Object, die das Interface implementiert. Lokale Klasse ist Anweisung in einem Block, anonyme Klasse Ausdruck als Teil eines grösseren Ausdrucks (z.B. Methodenaufruf). Info B VL 11: Innere Klassen/Collections – p.259 Eigenschaften von Anonymen Kl. (2) Verwendung: lokale Klasse, die nur einmal benutzt wird. (Definition und Nutzung genau dort, wo verwendet; weniger “clutter” im Code) Beschränkungen wie für lokale Klassen: keine statischen Komponenten, ausser static final Konstanten; nicht als public, private, protected, static deklarierbar. Da namenlos: keine Konstruktor-Definition möglich. Erbt – ausnahmsweise – die Konstruktoren der Oberklasse. Im Fall eines Interfaces wird ein Default-Konstruktor eingefügt. Wenn eigener/anderer Konstruktor notwendig, als lokale Klasse definieren. Alternative: Instanz-Initialisierer (für anonyme Klassen eingeführt), Initialisierungsblock wird in die geerbten Konstruktoren/den Default-Konstruktor eingefügt. Info B VL 11: Innere Klassen/Collections – p.260 Implementation f. Lokale Klassen Zusätzlich zu den Zugriffsrechten von Member-Klassen, Zugriff auf final deklarierte lokale Variablen im Geltungsbereich des Blocks, in dem sie definiert sind. Compiler gibt der inneren Klasse private Instanzfelder, um Kopien der lokalen Variablen zu halten. Compiler fügt versteckte Parameter für jeden Konstruktor einer lokalen Klasse ein, um diese private Felder zu initalisieren. Lokale Klasse hat nicht wirklich Zugriff auf die lokalen Variablen, sondern auf eine private Kopie dieser Variablen. final garantiert Konsistenz! “Hoch”-Compilation von anonymen Klassen: Vergabe von Nummern, z.B. MyListAC$1.class. Info B VL 11: Innere Klassen/Collections – p.261 Adapter Design Pattern sowie spezielle Java Adapter-Klassen. Adapter: Konvertierung eines API einer Klasse in das API einer anderen. Anwendung: Zusammenarbeit unverbundener Klassen Konzept: Schreibe Klasse mit dem gewünschten Interface und lasse diese Klasse mit der Klasse kommunizieren, die ein anderes Interface hat. Zwei Möglichkeiten zur Realisierung: Klassen-Adapter: Ableitung einer neuen Klasse von der nicht-angepassten Klasse und Hinzufügen von Methoden so, dass die neue Klasse dem gewünschten Interface genügt. Objekt-Adapter: Einbetten eines Objekts der ursprünglichen Klasse in die neue Klasse und Definition von Methoden, um Aufrufe in der neuen Klasse entsprechend zu übersetzen.Info B VL 11: Innere Klassen/Collections – p.262 Klassen-Adapter class A { // a class which "nearly" meets specification B } interface B { // ... } class AdA extends A implements B { // implement methods of B using A } Info B VL 11: Innere Klassen/Collections – p.263 Objekt-Adapter class AdA implements B { A a; // ... } Info B VL 11: Innere Klassen/Collections – p.264 Adapter für GUI-Prog. In Java wird der Begriff “Adapter” für Klassen im GUI-Bereich verwendet. Hier sind Adapter-Klassen Klassen, die nur Methoden mit leerem Körper zur Verfügung stellen. Anwendung: Erzeugung eines entsprechenden Objekts und Überschreiben der benötigten Methoden. Info B VL 11: Innere Klassen/Collections – p.265 ‘WindowAdapter’ (1) class MyWindowAdapter extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class Closer { public Closer() { MyWindowAdapter win = new MyWindowAdapter(); Frame f = new Frame(); f.addWindowListener(win); f.setSize(new Dimension(100,100)); f.setVisible(true); } public static void main(String[] args) { new Closer(); } } Info B VL 11: Innere Klassen/Collections – p.266 ‘WindowAdapter’ (2) Kompaktere Realisierung mit anonymer Klasse: // create window listener for window close addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); Info B VL 11: Innere Klassen/Collections – p.267 Innere Klassen und Lexical Closures Lexical Closure: Funktion, die ihren Kontext erinnert und freie Variablen darüber bindet. Konzept aus der funktionalen Programmierung. [1]> (defun adder (n) (function (lambda (m) (+ m n)))) ADDER [2]> (setq add3 (adder 3)) #<CLOSURE :LAMBDA (M) (+ M N)> [3]> (funcall add3 4) 7 Info B VL 11: Innere Klassen/Collections – p.268 Adder-Beispiel interface Adder{ int add(int m); } public Adder makeAdder(final int n) { return new Adder() { public int add (int m) {return m + n;} }; } In makeAdder wird das Adder-Interface für eine spezielle Anforderung adaptiert! Die anonyme innere Klasse realisiert das Konzept der lexical closure. Info B VL 11: Innere Klassen/Collections – p.269 ADTs und Collections Lernziele: Wiederholung/Ergänzung zu ADTs Illustration von OO-Prinzipien Lernen des Lesens von fremdem Code siehe Beispielprogramme im Paket adt Info B VL 11: Innere Klassen/Collections – p.270