6. Objekte, Klassen, ADTs Entwicklungsgeschichte 1. Vordefinierte Datentypen (In Java: int, float etc.) Datenbereich und Operationen durch die Sprache vordefiniert 2. Benutzerdefinierte Datentypen (In Java: array) Datenbereich durch den Programmierer mit Typkonstruktoren Operationen durch die Sprache vordefiniert 3. Abstrakte Datentypen (In Java: als Klassen realisiert) Sowohl Datenbereich als auch Operationen werden durch den Programmierer statisch definiert 4. Objekte und Klassen Datenbereich + Operationen durch Programmierer definiert Dynamische Erweiterung von Struktur und Verhalten László Böszörményi ESOP Objekte, Klassen, ADTs - 1
Objekte Grundidee Die modellierte Welt besteht aus selbständigen Objekten Jedes Objekt hat einen Zustandsraum (eine Menge von Variablen), der seine Vergangenheit speichert Der Zustandsraum ist von außen her direkt nicht erreichbar Objekte haben eine Menge von Operationen (Methoden), die an diesem Zustandsraum arbeiten Methoden sind meistens parametrisiert und können einen Rückgabewert liefern Objekte kommunizieren miteinander über Nachrichten, wodurch sie Methoden aktivieren können László Böszörményi ESOP Objekte, Klassen, ADTs - 2
Klassen Grundidee Objekte werden klassifiziert Objekte mit ähnlichem Verhalten gehören zur gleichen Klasse Die Beziehung zwischen Klasse und Objekt ist wie zwischen Typ und Wert (in Programmiersprachen) Die Klassendeklaration spezifiziert Struktur und Verhalten Ein Objekt ist eine konkrete Ausprägung (Instanz) einer Klasse Zwischen Klassen gibt es verschiedene Beziehungen Benützung (uses) Eine Klasse benutzt die Dienste einer anderen Klasse Z.B. Kundenobjekte benützen ein Bankobjekt Erweiterung (is-a) Eine Klasse erweitert die Dienste einer anderen Klasse Klasse PKW erweitert die Klasse Fahrzeug (PKW ist Fahrzeug) László Böszörményi ESOP Objekte, Klassen, ADTs - 3
Beispiel: Klassen und Objekte für Bankkonten Eine Bankanwendung bietet eine Klasse für Konten (Account) mit folgenden Methoden an deposit (Einzahlen), withdraw (Abheben), check (Kontostand abfragen) Objekte der Klasse der Klienten können ihre eigenen Konten-Objekte anlegen und benutzen Account 1 Account 2 deposit deposit withdraw withdraw Client 1 check Client 2 check capital == 100 capital == 300 László Böszörményi ESOP Objekte, Klassen, ADTs - 4
Klassen und Objekte in Java Eine Klasse ist ein benannter Typ und definiert Eine Menge von Variablen beliebigen Typs (inkl. Klasse) Eine Menge von (parametrisierten) Methoden (Operationen) Die Regeln der Sichtbarkeit ihrer Komponenten Ein Objekt ist eine Instanz einer Klasse Die Variablen erhalten eigenen Speicherplatz für jede Instanz Die vordefinierte Variable this referenziert das Objekt selbst Die Methoden können aufgerufen werden, und sie können auf den eigenen Variablen-Satz (die Instanzvariablen) zugreifen Beliebig viele Objekte einer Klasse können erzeugt werden Ein Objekt schickt einem anderen Objekt (Empfänger) eine Nachricht durch den Aufruf einer seiner Methode László Böszörményi ESOP Objekte, Klassen, ADTs - 5
Erzeugen und Löschen von Objekten Objekte werden dynamisch (zur Laufzeit) angelegt Account account1 = new Account(); Ein neues Account-Objekt wird angelegt Die Instanzvariablen werden initialisiert Der Konstruktor (siehe später) wird ausgeführt (wenn keiner definiert ist, dann der default- Konstruktor ) Objekte müssen nicht explizit gelöscht werden. Objekte, auf die keine Referenz mehr zeigt, verschwinden account1 = null; War account1 die einizige Referenz auf das Objekt, dann wird es vom garbage collector eingesammelt Arrays sind in Java auch Objekte darum so ähnlich László Böszörményi ESOP Objekte, Klassen, ADTs - 6
Objektvariablen sind in Java Referenzen Objektvariablen (Variablen die auf ein Objekt zeigen) enthalten immer Referenzen Instanzvariablen und Methoden eines Objektes können durch Dereferenzierung (. -Operator ) erreicht werden account1.deposit(x); Ruft Methode deposit vom Objekt account1 Anders gesagt: Objekt account1 empfängt die Nachricht deposit Die Zuweisung von Objekten hat Referenzsemantik Der Nullwert von Referenzvariablen (null) kann einer beliebigen Objektvariable zugewiesen werden Einer Variable vom Typ Object kann ein beliebiges Objekt zugewiesen werden (siehe auch später) László Böszörményi ESOP Objekte, Klassen, ADTs - 7
Statische Klassenkomponenten Klassen können statische (static) Variablen und Methoden deklarieren Diese gehören der Klasse selbst (dem Klassenobjekt) Sie werden statisch angelegt sie leben während der ganzen Ausführungszeit des Programms Sie können über den Klassennamen oder über beliebige Objektvariable der Klasse angesprochen werden Jedes Java Programm muss zumindest eine statische Komponente haben sonst kein fester Ankerpunkt Methode main muss in jedem Programm statisch sein Erhält von der Umgebung Aufruf und Parameter (String [] args) László Böszörményi ESOP Objekte, Klassen, ADTs - 8
Konstruktoren Konstruktoren sind spezielle Methoden, mit dem gleichen Namen wie die Klasse, und ohne Rückgabetyp Sie dienen für die Initialisierung des Objektzustands Sie werden durch new automatisch aufgerufen (nur so) Wenn kein Konstruktor definiert ist Ein parameterloser default-konstruktor wird erzeugt und Bei new aufgerufen um die Instanzvariablen zu initialisieren Eine Klasse kann mehrere Konstruktoren mit unterschiedlichen Signaturen haben Ein Konstruktor kann andere Konstruktoren der gleichen Klasse mit this(...) aufrufen (nur als 1. Anweisung) László Böszörményi ESOP Objekte, Klassen, ADTs - 9
Variablen und Konstruktoren der Klasse Account public class Account { // Klasse Account, 10.09.2000, LB // Konstanten, Instanzvariablen und Konstruktoren der Klasse Account static final double INITIAL = 0, // Konstanter Anfangswert für capital static final double MAX_CREDIT = 0; // Konstanter Anfangswert für max. credit double capital; double max_deficit; // Instanzvariable // Instanzvariable Account() {this (INITIAL, -MAX_CREDIT); } // Der 1. Konstruktor ruft den 2. Konstruktor mit default-werten auf Account(double initial, double max_credit) { // 2. Konstruktor, mit Parametern capital = initial; // capital this.capital... max_deficit = -max_credit; // max_deficit this. max_deficit... } // Account László Böszörményi ESOP Objekte, Klassen, ADTs - 10
Methoden der Klasse Account boolean deposit(double cash) { // Einzahlung, cash muss 0 sein boolean success = (cash >= 0); // Es wird geprüft, ob cash 0 if (success) { capital += cash; } // Cash wird einbezahlt return success; // Gibt true zurück, wenn cash 0, sonst false } // deposit boolean withdraw(double cash) {// Abheben, cash muss 0 sein wird nicht geprüft boolean success = (capital - cash >= max_deficit); // Prüft, ob Abheben möglich if (success ) { capital -= cash; } // Cash wird abgezogen return success; // Gibt true zurück, wenn Abheben erfolgreich war, sonst false } // withdraw double check() {return capital;} } // Account // Kontostand zurückgeben László Böszörményi ESOP Objekte, Klassen, ADTs - 11
public class BankClient { static void main(string [] args) { Account account = new Account(); double x = 0; Klasse BankClient // Benutzerklasse von Account, 17.09.2000, LB // Legt neues Account-Objekt an // Hilfsvariable do { Out.println(" >0:Einzahlen, <0:Abheben, =0:Aufhoeren"); x = In.readDouble(); if (x > 0) { account.deposit(x); else if (x < 0) { // Einzahlen // Erfolg wird nicht geprüft: muss sein // Abheben if (! account.withdraw(-x)) Out.println("Zu viel verlangt, sorry "); } // if (x < 0) Out.println("Kontostand = " + account.check()); } while (x!= 0); } // main } // BankClient Bei Eingabe 3, 5, 10, -7, 0: 3.0, 8.0, Zu viel verlangt, sorry 8.0, 1.0, 1.0 László Böszörményi ESOP Objekte, Klassen, ADTs - 12
Abstrakte Datentypen (ADT) Ein Abstrakter Datentyp (ADT) besteht aus Name, Datenbereich, Menge von Operationen Ein ADT spezifiziert, was die einzelnen Operationen bewirken, sagt aber nicht wie Die Spezifikation muss für die Benützung voll ausreichen Der Benutzer darf über das wie keine Annahmen treffen Die Spezifikation der Operationen besteht aus Spezifikation der Syntax Normalerweise eine Menge von Funktionen, als eine Abbildung: Urmenge (domain) Zielmenge (range) Spezifikation der Semantik In Form von Axiomen, z.b. in algebraischer Form László Böszörményi ESOP Objekte, Klassen, ADTs - 13
Spezifikation eines abstrakten Stacks Es sei S eine Menge von Zuständen, die durch eine endliche Anzahl von push und pop Operationen erreicht werden kann s 0 S ist ein ausgezeichneter Zustand, s 0 steht für den leeren Stack X ist der Datenbereich (bedingt durch den Datentyp) der Elemente die gestackt (gestapelt) werden können. Syntax 1. create: S 2. empty: S {true, false} push pop 3. push: S x X S 4. pop: S S 5. top: S X top Semantik ( s S, x X) 1. create = s 0 2. empty (s 0 ) = true 3. empty (push (s, x)) = false 4. empty(s) pop (push (s, x)) = s 5. empty(s) top (push (s, x)) = x empty(s) pop (push (s, x)) = (s, x) László Böszörményi ESOP Objekte, Klassen, ADTs - 14
Realisierung von ADTs mit Klassen Die Operationen können durch Methoden realisiert werden Die Semantik kann in allgemeinen Programmiersprachen wie Java nicht ausgedrückt werden Die Semantik muss extra (formal oder informal) angegeben werden Zusätzliche Dokumentation, Kommentare etc. werden benutzt Sichtbarkeit Java ermöglicht die öffentlichen und privaten Teile einer Klasse zu unterscheiden László Böszörményi ESOP Objekte, Klassen, ADTs - 15
Realisierung einer Stack-Klasse public class StackDouble{ int top = -1; double[] info; StackDouble(int max) { info = new double[max]; } // StackDouble // Kann double Zahlen stapeln // -1 steht für den leeren Stack // Der Stack-Speicher // Konstruktor mit Parameter boolean empty () {return top < 0;} void push (double d) { top++; info[top] = d; } /* push prüft zunächst nicht, ob Platz da ist */ double pop() { top--; return info[top + 1]; } /* pop prüft nicht, ob stack nicht leer ist */ push top pop } // StackDouble László Böszörményi ESOP Objekte, Klassen, ADTs - 16
Benutzerklasse vom StackDouble public class StackClient { static final int N = 8; static void main(string [] args) { StackDouble s = new StackDouble (N); double x = 1.5; for (int i = 0; i < N; i++) { Out.print(x + " "); s.push(x); } // main } // StackClient x += 0.5; } // for i Out.println(); while (! s.empty()) Out.print(s.pop() + " ") ; Out.println(); 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.0 4.5 4.0 3.5 3.0 2.5 2.0 1.5 László Böszörményi ESOP Objekte, Klassen, ADTs - 17
Realisierung von einem ADT für Brüche 1. public class Fraction { // Realisiert Operationen for Bruchzahlen int num, den; // Fraction = Numerator / Denominator (Zähler / Nenner) Fraction(int numer, int denom) {num = numer; den = denom; } // Konstruktor public String tostring () {return num + "/" + den;} //Wandelt Bruchzahl in Text um public Fraction copy() {return new Fraction(num, den);} // Erstellt eine Kopie public static Fraction plus (Fraction a, Fraction b) { // Klassenmethode Fraction x = a.copy(), y = b.copy(), z = new Fraction(1, 1); /* Wir kopieren a und b, um die Eingangsdaten nicht zu zerstören */ if (x.den!= y.den) { // Addition der Einfachheit halber ungekürzt x.num *= y.den; // (x.n/x.d) * (y.d/y.d) + y.num *= * x.den; // (y.n/y.d) * (x.d/x.d) = z.den = x.den * y.den; // (x.n*y.d + y.n*x.d) / (x.d * y.d) } else z.den = x.den; // x.n/x.d + y.n/x.d = (x.n + y.n) / x.d z.num = x.num + y.num; return z; } // plus László Böszörményi ESOP Objekte, Klassen, ADTs - 18
Realisierung von einem ADT für Brüche 2. public static Fraction minus (Fraction a, Fraction b) { return plus(a, new Fraction(-b.num, b.den)); } // minus // Klassenmethode // a - b a + (-b) public static Fraction times (Fraction a, Fraction b) { return new Fraction(a.num * b.num, a.den * b.den); } // times // Klassenmethode // == (a.n*b.n) / (a.d*b.d) public static Fraction div (Fraction a, Fraction b) { return times (a, new Fraction(b.den, b.num) ); } // div } // Fraction // Klassenmethode // a / b a * (1/b) László Böszörményi ESOP Objekte, Klassen, ADTs - 19
Benutzung vom ADT für Bruchzahlen public class FractionUser { // Benutzt die Klasse Fraction für Bruchzahlen static void main(string [] args) { Fraction a = new Fraction(1, 2); // Legt 1/2 an Fraction b = new Fraction(2, 3); // Legt 2/3 and Out.println(a + " + " + b + " = " + Fraction.plus(a, b) ); /* Äquivalent zu Out.println(a.toString() + " + " + b.tostring() + " = " + Fraction.plus(a, b).tostring() ); Typanpassung ruft automatisch die tostring Methode siehe auch später */ Out.println(a + " - " + b + " = " + Fraction.minus(a, b) ); Out.println(a + " * " + b + " = " + Fraction.times(a, b) ); Out.println(a + " / " + b + " = " + Fraction.div(a, b) ); } // main 1/2 + 2/3 = 7/6 1/2-2/3 = -1/6 } // FractionUser 1/2 * 2/3 = 2/6 1/2 / 2/3 = 3/4 László Böszörményi ESOP Objekte, Klassen, ADTs - 20