Innere Klassen Innere Klassen Lernziele: innere Klassen, statische geschachtelte Klassen, anonyme Klassen. Literatur: Java Tutorial & Arnold, K., Gosling, J. und Holmes,D ..... Page 1 Innere Klassen Der erste Eindruck in Java: alle Klassen sind "top level", gewöhnlich Eine pro Datei Klassen können jedoch innerhalb anderer Klassen deklariert werden. Warum: meist wenn eine Klasse nur innerhalb einer Anderen benötigt wird. Beispiel: verkettete Liste doppelt verkettete Liste: zwei Klassen ListenKnoten : enthält Daten und Pointer zum nächsten und vorherigen Knoten VerketteteListe : Pointer zu Kopf und Ende der Liste ListenKnoten ist Hilfsklasse und wird nur von VerketteteListe genutzt. VerketteteListe Kopf ListenKnoten Listenknoten ListenKnoten 1 2 3 Page 2 ListenKnoten 4 Ende Innere Klasse public class LinkedList { LinkedList Methoden ... können // inner class ListCell Objekte erzeugen private class ListCell { und nutzen. int value; ListCell next; Nutzer von ausserhalb der ListCell previous; LinkedList können die } // end ListCell ListCell Klasse nicht sehen – Implementierungs Detail private ListCell head; private ListCell tail; ... } // end LinkedList Innere Klasse kennt äussere Variablen public class OuterClassDemo { private int a; public InnerClass subObject; public class InnerClass { public int b; public int sum() { return a + b; } // end sum } // end class InnerClass // constructor Innere Klasse hat Referenz auf das a der äusseren Klasse. public OuterClassDemo( int aval, int bval) { a = aval; subObject = new InnerClass(); subObject. b = bval; } // end constructor public static void main( String args[]) { OuterClassDemo tester = new OuterClassDemo( 7, 5); System. out. println( tester. subObject. sum()); tester. a = 4; tester. subObject. b = 3; System. out. println( tester. subObject. sum()); } // end main } // end class OuterclassDemo Page 3 Grenzen der Inneren Klassen public class OuterClass { } .... public InnerClass subObject; public class InnerClass { public int b; .... } // end class InnerClass // end class OuterClass Ein äusserer Nutzer kann ein inneres Objekt referenzieren. OuterClass x = new OuterClass(); int y = x.subObject.b; Ein äusserer Nutzer kann KEINE Instanz eines inneren Objekts erzeugen. InnerClass y = new OuterClass.InnerClass(); // illegal Objekte 'Innerer Klassen' können nur innerhalb der äusseren Klasse existieren. Implementierungsdetails Unsere geistige Vorstellung von den Objekten: a: 13 subObject b: 7 Wie es in Java implementiert ist: a: 13 subObject b: 7 pointer vom inneren Objekt zum äusseren Objekt Page 4 Statische geschachtelte Klassen public class OuterClass { statische geschachtelte Klassen verhalten sich wie private int a; externe isolierte Klassen. public InnerClass subObject; Nur der Zugriff erfolgt über OuterName.innerName public static class InnerClass { public int b; Referenz zu `Member`-Variablen der public int sum() { äusseren Klasse ist unzulässig. return a + b; } // end sum } // end class InnerClass .............. Pointer vom `inneren Objekt´ zum äusseren Objekt existiert nicht! public static void main( String args[]) { OuterClass tester = new OuterClass( 7, 5); System. out. println( tester. subObject. sum()); tester. a = 4; tester. subObject. b = 3; System. out. println( tester. subObject. sum()); } // end main } Wozu statische geschachtelte Klassen? Eine Klasse innerhalb der anderen zu definieren spiegelt ihre Beziehung wieder. Wird oft bei Exceptions verwendet. public class MyClass { // data and methods for MyClass // MyClass may raise exceptions public static class MyException { .. } } // end MyClass MyException-Object muss nicht unbedingt Teil von MyClass sein, es könnte auch durch eine Methode in MyClass erzeugt werden. Page 5 Anonyme Klassen: Motivation Angenommen wir wünschen eine kleine Veränderung einer Klasse. Beispiel: ein Stack der automatisch `Debug´-Information ausgibt. 1. Lösung: erweitere eine Stackimplementierung. class DebugStack extends SuperStack { public void push(int i) { super.push(i); System.out.println("just put " + i); } public int pop() { int result = super.pop(); System.out.println("just got" + result); return result; } } Anonyme Klassen Was aber wenn wir nur eine einzige Instanz des Objekts benötigen. Dann kann eine Anonyme Klasse verwendet werden. Stack myStack = new Stack { public void push(int i) { super.push(i); System.out.println("just put " + i); } public int pop() { int result = super.pop(); System.out.println("just got " + result); return result; } } ; Anonyme Klassen sind nur nützlich wenn es darum geht Methoden zu erweitern und nicht um Neue zu schaffen. Page 6 Anonyme Klassen & Interfaces Anonyme Klassen können verwendet werden, wenn Objekte erzeugt werden sollen, die ein Interface implementieren. Stack myStack = new Stack() { public void push(int i) { ....} public int pop() {....} boolean isEmpty() {.....} }; Page 7