Beispiel: (geschütztes Zugriffsrecht) (3) Zusammenfassende

Werbung
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
5. Objektorientiertes Programmieren
Beispiel: (geschütztes Zugriffsrecht) (3)
Zusammenfassende Bemerkungen zu 5.3
• Subtypen erlauben es, spezialisierte Objekte anstelle von
public class Main {
public static void main( String [] args ) {
A_doch_Null adn = new A_doch_Null ();
adn.setA( 0 );
A_nicht_Null ann = adn;
... // hier koennte die Herkunft von ann
verschleiert sein
Anwendung .m(ann);
} }
Supertyp-Objekten zu verwenden. Dadurch können Programme
auf der Ebene allgemeinerer Objekte formuliert und
wiederverwendet werden.
• Vererbung erlaubt die Weitergabe und damit Wiederverwendung
von Programmteilen der Superklasse an die Subklasse.
• Subtypen in Kombination mit Vererbung erlauben eine direkte
Realisierung von Klassifikationen im Rahmen der
Programmierung.
Um Szenarien wie im obigen Beispiel zu vermeiden, sollten
Subklassen-Objekte das Verhalten der Superklassen-Objekte
spezialisieren und sich ansonsten konform verhalten.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
5.3 Subtypen und Vererbung
• Die Vorteile wirken sich vor allem bei der Entwicklung von
Programmbibliotheken und Programmgerüsten/Frameworks aus.
1349
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
Abschnitt 5.4
1350
5.4 Objektorientierte Bausteine und Bibliotheken
Objektorientierte Bausteine und Bibliotheken
Dieser Abschnitt führt in den Komponenten-/Bausteinbegriff und in die
Java-Bibliothek ein.
Ziel ist die Vertiefung der in 5.3 erläuterten Konzepte und deren
Anwendung.
Objektorientierte Bausteine und Bibliotheken
Überblick:
• Bausteine, Schnittstellen und Bibliotheken
• Klassen zur Ausnahmebehandlung
• Ströme zur Ein- und Ausgabe
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1351
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1352
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Unterabschnitt 5.4.1
5.4 Objektorientierte Bausteine und Bibliotheken
Bausteine, Schnittstellen und Bibliotheken
• Klärung und Diskussion der Begriffe
Bausteine, Schnittstellen und Bibliotheken
I
Programmbaustein, -komponente
I
API, Programmierschnittstelle
I
Bibliothek
• Überblick über die Java-Bibliothek
Dabei verwenden wir die Begriffe ”Programmbaustein” und
”Programmkomponente” hier synonym.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1353
5.4 Objektorientierte Bausteine und Bibliotheken
• Wie anpassbar, wie allgemein sind die Bausteine?
• Anpassen der Bausteine:
• Sind die Bausteine direkt einsetzbar oder müssen sie noch
vervollständigt werden?
Instanzieren von Parametern
Spezialisierung
• Sind die Bausteine unabhängig voneinander, hierarchisch
strukturiert, wechselseitig abhängig?
• Verbinden der Bausteine/Komposition:
I
• Wie werden sie zusammengesetzt?
Verbindungsmechanismen der Komponenten
zusätzlicher Programmcode (engl. glue code)
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
Wichtige Fragestellungen:
Konstruiere Softwaresysteme aus vorgefertigten Bausteinen durch
I
1354
Programmbausteine & Komponenten (2)
Idee der komponentenbasierten Softwarekonstruktion:
I
TU Kaiserslautern
5. Objektorientiertes Programmieren
Programmbausteine & Komponenten
I
©Arnd Poetzsch-Heffter
TU Kaiserslautern
• Wie kann man sie auffinden?
1355
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1356
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Programmbausteine & Komponenten (3)
Begriffsklärung: (unabhängige Bausteine)
Vereinfachend gehen wir davon aus, dass ein Baustein durch eine
oder mehrere Typdeklarationen realisiert ist. Die Schnittstelle eines
Bausteins entspricht der öffentlichen Schnittstelle dieser Typen.
Wir nennen Bausteine oder Programmkomponenten unabhängig,
wenn sie ohne Kenntnis und Existenz anderer Bausteine bzw.
Komponenten angewandt werden können.
Wir betrachten drei Arten von Bausteinen:
In der Schnittstelle unabhängiger Bausteine kommen im Wesentlichen
nur vordefinierte und Standardtypen vor.
• unabhängige Bausteine
• eigenständige Bausteine
Typische Beispiele sind einfache Behälterbausteine (z.B. SLinkedList),
die Klasse String oder die Wrapper-Klassen, aber auch vollständige
Anwendungsprogramme.
• kooperierende Bausteine
Wir erläutern diese Aufteilung jeweils durch Begriffsklärung und
Beispiele in Java.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1357
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
Boolean ( boolean value ){ this.value = value; }
Boolean ( String s) { this( toBoolean (s) ); }
boolean booleanValue (){ return value; }
static Boolean valueOf ( String s){...}
String toString () { ... }
int hashCode () { ... }
TU Kaiserslautern
1358
5.4 Objektorientierte Bausteine und Bibliotheken
Beispiel: (unabhängiger "Baustein") (2)
public final class Boolean implements java.io.
Serializable {
public static final Boolean TRUE = new Boolean (true);
public static final Boolean FALSE = new Boolean ( false);
public static final Class <Boolean > TYPE = ...;
private final boolean value ;
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
Beispiel: (unabhängiger "Baustein")
public
public
public
public
public
public
5.4 Objektorientierte Bausteine und Bibliotheken
}
1359
public boolean equals ( Object obj) {
if (obj instanceof Boolean ) {
return value == (( Boolean )obj). booleanValue ();
}
return false ;
}
public static boolean getBoolean ( String n){..}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1360
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
Bemerkungen:
Begriffsklärung: (eigenständige Bausteine)
Unabhängigkeit erleichtert das Verständnis von Bausteinen. Trotzdem
sind unabhängige Bausteine in Programmbibliotheken eher selten.
Wir nennen Bausteine oder Programmkomponenten eigenständig,
wenn die Kenntnis und Existenz ihrer Supertypen für ihr Verständnis
und ihre Anwendung ausreicht und sie eingesetzt werden können,
ohne mit anderen Bausteinen kooperieren zu müssen.
Häufig sind unterschiedliche, aber ähnliche Bausteine Teil einer
Klassen- bzw. Typhierarchie. Dadurch sind speziellere Bausteine oft
von allgemeineren abhängig.
In der Schnittstelle eigenständiger Bausteine kommen im
Wesentlichen nur vordefinierte Typen, Standardtypen und Supertypen
der Klassen vor, die den Baustein implementieren.
Typische Beispiele sind komplexere Behälterbausteine und
Stromklassen.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1361
5.4 Objektorientierte Bausteine und Bibliotheken
1362
5.4 Objektorientierte Bausteine und Bibliotheken
Beispiel: (eigenstängiger Baustein) (2)
public interface ListIterator
extends Iterator {
boolean hasNext ();
Object next ();
boolean hasPrevious ();
Object previous ();
int nextIndex ();
int previousIndex ();
void remove ();
void set( Object o);
void add( Object o);
}
Listen mit Iteratoren bilden einen Baustein.
Als Beispiel betrachten wir die Typen LinkedList, Iterator und
ListIterator aus dem Paket java.util (Version ohne Parametrisierung;
Java 4 und früher).
public interface Iterator {
boolean hasNext ();
Object next ();
void remove ();
}
TU Kaiserslautern
TU Kaiserslautern
5. Objektorientiertes Programmieren
Beispiel: (eigenstängiger Baustein)
©Arnd Poetzsch-Heffter
©Arnd Poetzsch-Heffter
1363
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1364
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Beispiel: (eigenstängiger Baustein) (3)
Beispiel: (eigenstängiger Baustein) (4)
public class LinkedList
extends AbstractSequentialList
implements List , Cloneable , Serializable
{
public LinkedList ()
public LinkedList ( Collection c)
public Object getFirst ()
public Object getLast ()
public Object removeFirst ()
public Object removeLast ()
public void addFirst ( Object o)
public void addLast ( Object o)
public boolean contains ( Object o)
public int size ()
public boolean add( Object o)
public boolean remove ( Object o)
public boolean addAll ( Collection c)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
public
public
public
public
public
public
public
public
// ...
1365
}
©Arnd Poetzsch-Heffter
boolean addAll (int ix , Collection c)
void clear ()
Object get(int index)
Object set(int ix , Object elem)
void add(int index , Object elem)
Object remove (int index )
int indexOf ( Object o)
int lastIndexOf ( Object o)
weiter naechste Seite
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
Beispiel: (eigenstängiger Baustein) (5)
// ...
public
public
public
public
public
public
public
public
public
... //
5.4 Objektorientierte Bausteine und Bibliotheken
1366
5.4 Objektorientierte Bausteine und Bibliotheken
Bemerkung:
In Abschnitt 5.4.3 werden wir weitere eigenständige Bausteine kennen
lernen.
ListIterator listIterator ()
ListIterator listIterator (int ix)
Iterator iterator ()
List subList (int from , int to)
boolean equals ( Object o)
int hashCode ()
Object clone ()
Object [] toArray ()
Object [] toArray ( Object a[])
Methoden aus Object
Im Allg. agieren Bausteine nicht eigenständig, sondern müssen mit
anderen und andersartigen Bausteinen kooperieren, um ihre
Funktionalität zu erbringen.
Bausteine können eng oder nur lose kooperieren. Enge Kooperation
findet man typischerweise in Programmgerüsten (engl. program
frameworks).
Die Kooperation zwischen Bausteinen kann man syntaktisch an den
(rekursiven) Abhängigkeiten der Typdeklarationen erkennen.
TU Kaiserslautern
1367
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1368
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Beispiel: (Abhängigkeiten bei Kooperation)
5.4 Objektorientierte Bausteine und Bibliotheken
Bemerkung:
Folgende Fragmente stammen aus dem AWT (Pakete java.awt, etc.):
class Component ... { ...
void addComponentListener ( ComponentListener c)
...
}
• Die Grenzen eines Bausteins werden vom Bausteinentwickler
festgelegt und lassen sich im Allg. nicht aus dem Programmtext
erschließen.
interface ComponentListener ... { ...
void componentResized ( ComponentEvent e );
...
}
• Die Unterscheidung zwischen den Bausteinarten ist nicht scharf.
class ComponentEvent ... { ...
Component getComponent () ...
...
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1369
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
Begriffsklärung: (Programmierschnittstelle)
1370
5.4 Objektorientierte Bausteine und Bibliotheken
Beispiele: (Programmierschnittstellen)
Es gibt Programmierschnittstellen für den:
• Zugriff aufs Dateisystem
Die Programmierschnittstelle eines Bausteins (einer Komponente)
besteht aus den öffentlichen Typen und Methoden, mit denen der
Baustein aus Programmen heraus gesteuert werden kann.
• Zugriff auf andere Teile des Betriebssystems
• Zugriff aufs Netzwerk
In gleicher Weise spricht man von der Programmierschnittstelle einer
Anwendung oder eines Systems (engl. application programming
interface, API).
• Zugriff auf eine Anwendung, etwa ein Spiel
Bemerkung
Nicht alles, was sich API nennt, ist in obigem Sinne eine
Programmierschnittstelle.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1371
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1372
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Begriffsklärung: (Programmbibliothek)
5.4 Objektorientierte Bausteine und Bibliotheken
Beispiele: (Programmbibliotheken)
• zu Programmiersprachen gehörende Standardbibliotheken (z.B.
Java-Bibliothek)
Eine Programmbibliothek oder einfach Bibliothek ist eine
strukturierte Ansammlung von Programmteilen, die für die
Wiederverwendung entwickelt und organisiert sind.
• Bibliotheken für Datenstrukturen: STL, Leda, ...
• Bibliotheken für graphische Bedienoberflächen, für allgemeine
Die Programmteile können unterschiedlicher Art sein (z.B.
standardisierte Bausteine der Sprache, eigenständige Bausteine,
Programmierschnittstellen, Programmgerüste).
Anwendungsbaukästen
• Bibliotheken für Graphik, CAD, virtuelle Welten, ...
• Anwendungsspezifische Bibliotheken
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1373
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
Wichtige Pakete der Java-Bibliothek
1374
5.4 Objektorientierte Bausteine und Bibliotheken
Bemerkung:
Die obige Darstellung der Java-Bibliothek ist unvollständig.
Beispielsweise enthält das Paket javax.swing ein leistungsfähigeres
Programmgerüst zur Realisierung graphischer Bedienoberflächen
(GUI Framework).
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1375
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1376
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Unterabschnitt 5.4.2
5.4 Objektorientierte Bausteine und Bibliotheken
Klassen zur Ausnahmebehandlung
Realisierung der Ausnahmebehandlung in Java demonstriert zwei
Aspekte:
• erweiterbare Hierarchie einfacher Bausteine
• Zusammenspiel von Sprache und Standardbibliothek
Klassen zur Ausnahmebehandlung
Darüber hinaus ist das Verständnis der Ausnahmebehandlung von
allgemeinem Interesse für die Softwareentwicklung.
Die möglichen Ausnahmesituationen werden in Java durch eine
Typhierarchie klassifiziert.
Alle Ausnahmeklassen sind Subklassen von java.lang.Throwable .
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1377
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Klassifikation von Ausnahmesituationen
1378
5.4 Objektorientierte Bausteine und Bibliotheken
Klassifikation von Ausnahmesituationen (2)
2. Programmierfehler (RuntimeException):
Es gibt drei Arten von Ausnahmesituationen:
Typische Beispiele:
1. Nicht korrigierbare Ausnahmesituationen (Error):
• Dereferenzieren von null (NullPointerException):
Drei typische Beispiele:
Object ov = null;
ov. equals ( new Object () );
• kein Speicherplatz mehr verfügbar zum Erzeugen von Objekten
(OutOfMemoryError)
• Feldzugriff mit unzulässigem Index
• zuviele unbeendete Methodenaufrufe (StackOverflowError)
(IndexOutOfBoundsException):
int [] iav = new int [37];
int n = iav [333];
• Inkonsistenzen zwischen übersetzten Klassen (z.B.
AbstractMethodError)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
TU Kaiserslautern
1379
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1380
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Klassifikation von Ausnahmesituationen (3)
5.4 Objektorientierte Bausteine und Bibliotheken
Beispiel: (anwendungsspezifische Ausnahme)
3. Nicht vermeidbare, aber behandelbare Situationen:
Beispiele sind der Zugriff auf eine Ressource, etwa das Netz oder eine
Datei, die augenblicklich anderweitig genutzt wird.
Abhilfe:
• zeitverzögert nochmaligen Zugriff
• Anwendung einer vergleichbaren Ressource.
In diese Kategorie fallen auch die meisten anwendungsspezifischen
Ausnahmen.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1381
public class KeinKaffeeException
extends Exception {
private float restMenge ;
KeinKaffeeException ( float kaffeeMenge ){
restMenge = kaffeeMenge ;
}
public float getRestMenge () {
return restMenge ;
}
}
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
Hierarchie der Ausnahmetypen
1382
5.4 Objektorientierte Bausteine und Bibliotheken
Zusammenspiel von Sprache und Bibliothek
Die Ausnahmebehandlung in Java hat vier Aspekte:
1. Welche Ausnahmen gibt es?
2. Wodurch werden Ausnahmen ausgelöst?
3. Wie werden Ausnahmen ggf. über Methodengrenzen hinweg
weitergereicht?
4. Wie kann man Ausnahmen abfangen und behandeln?
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1383
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1384
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Zusammenspiel von Sprache und Bibliothek (2)
5.4 Objektorientierte Bausteine und Bibliotheken
Zusammenspiel von Sprache und Bibliothek (3)
1. Aspekt:
3. Aspekt:
Ausnahmen als Subklassen von Throwable realisiert; d.h.
Behandlung von Ausnahmen:
• vordefinierte Ausnahmen in der Standardbibliothek
• im umfassenden try-Block;
• benutzerdefinierte Ausnahmen als Subklassen
• die aktuelle Methode terminiert abrupt und reicht die Ausnahme
an die Aufrufstelle weiter.
2. Aspekt:
Fehler und Laufzeitausnahmen werden durch das Laufzeitsystem von
Java (Java Virtual Machine) ausgelöst.
Der Java-Übersetzer prüft, welche Ausnahmen eine Methode
möglicherweise auslöst, ohne sie abzufangen.
Andere Ausnahmen durch Systemschnittstellen oder
Anwenderprogramme mittels der throw-Anweisung.
Alle nicht-abgefangenen Ausnahmen, die weder Subklassen von Error
noch von RunTimeException sind, müssen in der Signatur der
Methode deklariert werden (siehe Beispiel).
Der Ausdruck in der throw-Anweisung muss von einem Subtyp von
Throwable sein.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1385
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
Zusammenspiel von Sprache und Bibliothek (4)
1386
5.4 Objektorientierte Bausteine und Bibliotheken
Beispiel: (Ausnahmebehandlung)
4. Aspekt:
Mittels der try-catch-Anweisung kann man Ausnahmen (und Fehler)
abfangen:
try {
<Anweisungsblock1 >
} catch( <Subtyp von Throwable > eb ) {
<Anweisungsblock2 >
} ...
Tritt im Anweisungsblock1 eine Ausnahme vom Typ E auf und ist E ein
Subtyp des Typs, der in der catch-Klausel genannt ist, dann wird die
Ausnahme abgefangen und der Anweisungsblock2 ausgeführt.
public class KaffeeMaschine {
private KaffeeSpeicher speicher ;
...
void fuellenFilter ( float benoetigteMenge )
throws KeinKaffeeException {
float restMenge ;
restMenge = speicher . messenFuellung ();
if( restMenge < benoetigteMenge ) {
throw new KeinKaffeeException ( restMenge );
}
...
}
}
Andernfalls wird die Ausnahme weitergereicht.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1387
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1388
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Bemerkung:
5.4 Objektorientierte Bausteine und Bibliotheken
Unterabschnitt 5.4.3
• Häufig kann die Behandlung der Ausnahme erst von einem weiter
außen liegenden Aufrufer erledigt werden.
Ströme zur Ein- und Ausgabe
• Eine überschreibende Methode darf nur die Ausnahmen
auslösen, die auch die überschriebene Methode auslösen darf.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1389
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
1390
5.4 Objektorientierte Bausteine und Bibliotheken
Ströme zur Ein- und Ausgabe
Ströme zur Ein- und Ausgabe (2)
Ein- und Ausgabe von Daten wird heutzutage meist durch Ströme
modelliert.
Sowohl beim Schreiben in einen Strom als auch beim Lesen aus einen
Strom kann es zu Verzögerungen kommen:
Begriffsklärung: (Datenstrom)
• beim Lesen, weil augenblicklich kein Zeichen vorhanden, der
Strom aber noch nicht zu Ende ist;
Ein Strom ist eine potentiell unendliche Folge von Daten.
Er wird von einer oder mehrerer Quellen mit Daten versorgt und
erlaubt es, diese Daten der Reihe nach aus dem Strom herauszulesen.
Die Verzögerungen führen zu einer Blockierung der ausgeführten
Methode.
Das Ende eines Stromes wird durch ein spezielles Datum (in Java ist
das -1) markiert.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
• beim Schreiben, weil ggf. kein Platz im Strom vorhanden ist.
1391
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1392
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Bemerkung:
5.4 Objektorientierte Bausteine und Bibliotheken
Einführung in Ströme
• Stromklassen sind in diesem Kontext interessant:
I
als wichtige Programmierschnittstelle
I
als Beispiel für Typhierarchien und eigenständige Bausteine
I
als Beispiel für Komposition von Bausteinen
Wir betrachten zunächst Ströme zum Lesen:
interface CharEingabeStrom {
int read () throws IOException ;
}
• vergleiche auch unendliche Listen in Haskell (vgl. F. 306).
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1393
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
Einführung in Ströme (2)
Lesen aus einer Datenstruktur:
Diese Schnittstelle abstrahiert von der Quelle aus der gelesen wird.
Mögliche Quellen:
Wir betrachten das schrittweise Lesen der Zeichen eines Strings. Die
Quelle des Stroms wird dem Stromkonstruktor übergeben.
public class StringLeser implements CharEingabeStrom {
private char [] dieZeichen ;
private int
index = 0;
1. Datenstruktur wie Feld, Liste, String.
2. Datei
public StringLeser ( String s ) {
dieZeichen = s. toCharArray ();
}
3. Netzwerk
4. Standardeingabe, z.B. interaktive Eingabe vom Anwender
5. andere Programme
6. andere Ströme
}
Wir betrachten hier die Fälle 1, 2 und 6
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1394
1395
public int read () {
if( index == dieZeichen . length ) return -1;
else return dieZeichen [index ++];
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1396
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Zusammenbauen von Strömen:
5.4 Objektorientierte Bausteine und Bibliotheken
Zusammenbauen von Strömen: (2)
public class GrossBuchstabenFilter
implements CharEingabeStrom {
private CharEingabeStrom eingabeStrom ;
Wir betrachten zwei Stromklassen, die aus anderen Strömen lesen
und die Ströme modifizieren.
public GrossBuchstabenFilter ( CharEingabeStrom cs ) {
eingabeStrom = cs;
}
Die Konstruktoren nehmen dabei einen beliebigen CharEingabeStrom
als Quelle:
→ Subtyping at its best!
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1397
public int read () throws IOException {
int z = eingabeStrom .read ();
if( z == -1 ) {
return -1;
} else {
return Character . toUpperCase ( (char)z );
}
}
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Zusammenbauen von Strömen: (3)
public UmlautSzFilter ( CharEingabeStrom cs ){
eingabeStrom = cs;
}
public int read () throws IOException {
if( puffer != -1 ) {
int z = puffer ;
puffer = -1;
return z;
} else {
...
TU Kaiserslautern
1398
5.4 Objektorientierte Bausteine und Bibliotheken
Zusammenbauen von Strömen: (4)
public class UmlautSzFilter implements CharEingabeStrom {
private CharEingabeStrom eingabeStrom ;
private int puffer = -1;
©Arnd Poetzsch-Heffter
TU Kaiserslautern
}
}
}
int z = eingabeStrom .read ();
if( z == -1 ) return -1;
switch ( (char)z ) {
case ’\u00C4 ’: puffer = ’e’;
case ’\u00D6 ’: puffer = ’e’;
case ’\u00DC ’: puffer = ’e’;
case ’\u00E4 ’: puffer = ’e’;
case ’\u00F6 ’: puffer = ’e’;
case ’\u00FC ’: puffer = ’e’;
case ’\u00DF ’: puffer = ’s’;
default :
return z;
}
return
return
return
return
return
return
return
’A’;
’O’;
’U’;
’a’;
’o’;
’u’;
’s’;
Folgendes Programm zeigt Zusammenbau und Anwendung von
Strömen:
1399
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1400
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
Zusammenbauen von Strömen: (5)
Adaption von Strömen:
public class Main {
public static void main( String [] a) throws IOException {
String s = new String ("\ u00C4neas opfert den "
+ "G\ u00D6ttern edle \u00D6le ,\ nauf da\u00DF "
+ "\ u00FCberall das \ u00DCbel sich \ u00E4ndert .");
Adaption bedeutet in der Objektorientierung meist das Anpassen einer
Schnittstelle an die Bedürfnisse eines Anwenders.
} }
Als kleines Beispiel einer Adaption betrachten wir die typmäßige
Anpassung der Klasse FileReader aus java.io an CharEingabeStrom:
CharEingabeStrom cs = new StringLeser ( s );
cs = new UmlautSzFilter ( cs );
cs = new GrossBuchstabenFilter ( cs );
int z = cs.read ();
while ( z != -1 ) {
System .out. print ( (char)z );
z = cs.read ();
}
System .out. println ("");
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1401
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
Adaption von Strömen: (2)
Javas Stromklassen
Da FileReader eine Methode read mit der gleichen Signatur und
Bedeutung wie in CharEingabeStrom bereitstellt, reicht folgende fast
triviale Adaptionsklasse:
Stromklassen werden nach den Datentypen, die sie verarbeiten, und
ihre Quellen bzw. Senken klassifiziert.
public class DateiLeser extends FileReader
implements CharEingabeStrom {
}
Stromklassen sind wichtige programmiertechnische Hilfsmittel und ihre
Hierarchien ein gutes Beispiel für eigenständige Bausteine.
public DateiLeser ( String s ) throws IOException {
super (s);
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1402
Die Reader-/Writer-Klassen aus dem Paket java.io verarbeiten
char-Ströme; die Input-/Output-Stromklassen verarbeiten byte-Ströme.
1403
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1404
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Javas Stromklassen (2)
Javas Stromklassen (3)
Die Reader-Klassen unterstützen:
Die Writer-Klassen unterstützen:
• das Schreiben einzelner Zeichen:
• das Lesen einzelner Zeichen: int read();
void write( int ) ;
• das Lesen mehrerer Zeichen aus der Quelle und Ablage in ein
char-Feld: int read(char[]);
• das Schreiben mehrerer Zeichen eines char-Feldes:
• das Überspringen einer Anzahl von Zeichen der Eingabe:
long skip(long);
void write(char [])
u. ä.;
• die Abfrage, ob der Strom für das Lesen des nächsten Zeichens
bereit ist;
• das Schreiben mehrerer Zeichen eines String:
• das Schließen des Eingabestroms: void close();
void write( String )
• Methoden zum Markieren und Zurücksetzen des Stroms.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
u. ä.;
1405
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
Javas Stromklassen (4)
1406
5.4 Objektorientierte Bausteine und Bibliotheken
Reader-/Writer-Klassen:
Die Reader-Klassen unterscheiden sich im Wesentlichen durch ihre
Quelle:
• die Ausgabe ggf. im Strom gepufferter Zeichen:
void flush () ;
• das Schließen des Ausgabestroms:
void close ().
Die genannten Methoden lösen möglicherweise eine IOException aus.
Die von InputStream bzw. OutputStream abgeleiteten Klassen leisten
Entsprechendes für Daten vom Typ byte.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1407
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1408
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Reader-/Writer-Klassen: (2)
Reader-Klasse
InputStreamReader
FileReader
BufferedReader
LineNumberReader
PipedReader
FilterReader
PushBackReader
CharArrayReader
StringReader
©Arnd Poetzsch-Heffter
Quelle
InputStream
byte-Strom
aus Datei
Reader
Reader
PipedWriter
Reader
Reader
char[]
String
Reader-/Writer-Klassen: (3)
Bemerkung
puffernd; können
zeilenweise lesen
Methode unread
Writer arbeiten analog zu Reader-Klassen, nur in umgekehrter
Richtung.
PrintWriter unterstützen die formatierte Ausgabe von Daten durch die
Methoden print und println, die alle Standarddatentypen als Parameter
nehmen.
TU Kaiserslautern
5. Objektorientiertes Programmieren
1409
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
Bemerkung:
1410
5.4 Objektorientierte Bausteine und Bibliotheken
Beispiel: (Reader-/Writer-Klassen)
public class DateiZugriff {
public static String lesen( String datei )
throws FileNotFoundException , IOException {
BufferedReader in =
new BufferedReader (new FileReader (datei));
String line , inputstr = "";
line = in. readLine ();
while ( line != null ){
inputstr = inputstr . concat ( line+"\n");
line = in. readLine ();
}
in. close ();
return inputstr ;
}
Die Konstruktoren ermöglichen das Zusammenhängen von Strömen;
hier am Beispiel eines Konstruktors der Klasse PrintWriter:
public PrintWriter ( OutputStream o, boolean af ) {
this( new BufferedWriter (
new OutputStreamWriter (o)), af );
}
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
1411
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1412
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Beispiel: (Reader-/Writer-Klassen) (2)
Beispiel: (Reader-/Writer-Klassen) (3)
public class DateiZugriffTest {
public static void main( String [] argf ){
String s;
try {
s = DateiZugriff .lesen ( argf [0] );
} catch( FileNotFoundException e ){
System .out. println ("Can ’t open "+ argf [0]);
return ;
} catch( IOException e ){
System .out. println (" IOException : "+ argf [0]);
return ;
}
public static void schreiben ( String datei , String s)
throws IOException {
PrintWriter out;
out = new PrintWriter ( new FileWriter ( datei ) );
out. print ( s );
out. close ();
}
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1413
}
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
Beispiel: (Reader-/Writer-Klassen) (4)
}
5.4 Objektorientierte Bausteine und Bibliotheken
1414
5.4 Objektorientierte Bausteine und Bibliotheken
Input-/Outputstream-Klassen:
try {
DateiZugriff . schreiben (" ausgabeDatei ",s);
} catch ( IOException e ){
System .out. println ("Can ’t open "+ argf [0] );
}
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1415
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1416
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
Objektströme
Objektströme (2)
Das Lesen und Schreiben von den Werten der elementaren
Datentypen ist relativ einfach. Sie besitzen eindeutige
Repräsentationen.
Andererseits ist Ein- und Ausgabe von Objekten wichtig, um
Die Ein- und Ausgabe von Objekten ist komplexer:
• Objekte zwischen Prozessen auszutauschen;
• Der Zustand reicht zur Repräsentation eines Objektes nicht aus.
• Objekte für nachfolgende Programmläufe zu speichern, d.h.
• Objektreferenzen besitzen nur innerhalb des aktuellen Prozesses
persistent zu machen.
eine Gültigkeit.
• Bei Objekten ist häufig ihre Rolle im Objektgeflecht von
entscheidender Bedeutung.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1417
5.4 Objektorientierte Bausteine und Bibliotheken
1418
5.4 Objektorientierte Bausteine und Bibliotheken
Beispiel: (Objekte: Wie ausgeben?) (2)
Was bedeutet es, das von ll referenzierte Objekt auszugeben(?):
LinkedList ll = new LinkedList ();
StringBuffer s = new StringBuffer ("Sand");
ll.add("Sich ");
ll.add("mit ");
ll.add(s);
ll.add("alen ");
ll.add("im ");
ll.add(s);
ll.add(" aalen ");
TU Kaiserslautern
TU Kaiserslautern
5. Objektorientiertes Programmieren
Beispiel: (Objekte: Wie ausgeben?)
©Arnd Poetzsch-Heffter
©Arnd Poetzsch-Heffter
• nur das LinkedList-Objekt ausgeben;
• das LinkedList-Objekt und die zugehörigen Entry-Objekte
ausgeben;
• das LinkedList-Objekt, die zugehörigen Entry-Objekte sowie die
String-Objekte und das StringBuffer-Objekt ausgeben.
1419
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1420
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
Ausgabe von Objektgeflechten
Beispiel: (Ausgabe von Objektgeflechten)
Um Objekte in ihrem Zusammenwirken mit anderen Objekten wieder
einlesen zu können, müssen sie gemeinsam mit allen erreichbaren
Objekten ausgegeben werden.
Sei die Variable ll wie in obigem Beispiel:
OutputStream os = new FileOutputStream (" ausgabeDatei ");
ObjectOutputStream oos = new ObjectOutputStream ( os );
oos. writeObject ( ll );
Dabei bekommen sie eine Kennung, die relativ zu den anderen
Objekten des Geflechts eindeutig ist.
Der Methodenaufruf in der letzten Zeile führt zur Ausgabe aller von ll
aus erreichbaren Objekte in die Datei mit Namen „ausgabeDatei“.
Wg. möglicher Zyklen ist die Implementierung der Ausgabe und des
Einlesens von Geflechten nicht einfach. Darum gibt es dafür eine
Unterstützung in der Bibliothek.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1421
5.4 Objektorientierte Bausteine und Bibliotheken
1422
5.4 Objektorientierte Bausteine und Bibliotheken
Beispiel: (Einlesen von Objektgeflechten)
Das Einlesen von Objekten und den mit ihnen abgelegten
erreichbaren Objekten birgt eine weitere Schwierigkeit:
Beim Einlesen müssen Objekte erzeugt werden.
Dafür müssen alle Klassen der einzulesenden Objekte und geeignete
Konstruktoren zur Verfügung stehen. (Zum Auffinden benutzt Java die
Mechanismen der Reflexion.)
TU Kaiserslautern
TU Kaiserslautern
5. Objektorientiertes Programmieren
Ausgabe von Objektgeflechten
©Arnd Poetzsch-Heffter
©Arnd Poetzsch-Heffter
1423
LinkedList inll;
InputStream is = new FileInputStream (" ausgabeDatei ");
ObjectInputStream ois = new ObjectInputStream ( is );
try {
inll = ( LinkedList )ois. readObject ();
} catch( ClassNotFoundException exc ) {
System .out. println (" Klasse zu Objekt fehlt");
}
Der Methodenaufruf ois.readObject() liest ein Objektgeflecht aus der
Datei mit Namen „ausgabeDatei“ ein.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1424
5. Objektorientiertes Programmieren
5.4 Objektorientierte Bausteine und Bibliotheken
5. Objektorientiertes Programmieren
Zur Beachtung:
5.4 Objektorientierte Bausteine und Bibliotheken
Beispiel: (Ausgabe u. Einlesen von Objekten)
Ausgabe und Einlesen der von a und c referenzierten Objekte und
Geflechte:
• Gibt man ein Objekt mit den erreichbaren Objekten aus und liest
es wieder ein, entsteht eine Kopie.
• Referenziert man von mehreren Variablen Teile des gleichen
Geflechts, kommt es beim Einlesen ggf. zu mehreren Kopien
eines Objekts des ursprünglichen Geflechts.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
5. Objektorientiertes Programmieren
1425
©Arnd Poetzsch-Heffter
5.4 Objektorientierte Bausteine und Bibliotheken
TU Kaiserslautern
5. Objektorientiertes Programmieren
Begriffsklärung: (Serialisieren)
1426
5.4 Objektorientierte Bausteine und Bibliotheken
Bemerkung:
• Serialisieren hat zwei zentrale Anwendungen:
Serialisieren bedeutet alle von einem Objekt aus erreichbaren
Objekte der Reihe nach in kodierter Form in einen Strom zu schreiben.
I
Persistenz von Objekten zu unterstützen;
I
Parameterübergabe bei der verteilten objektorientierten
Programmen zu realisieren.
• Der Serialisierungsmechanismus muss im Allg. Zugriff auf private
Deserialisieren bezeichnet den umgekehrten Prozess.
Daten haben und adaptierbar sein.
• In Java wird die Serialisierbarkeit der Objekte einer Klasse K
dadurch ausgedrückt, dass K die Schnittstelle Serializable
implementiert.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1427
©Arnd Poetzsch-Heffter
TU Kaiserslautern
1428
Herunterladen