Prg08-Objekte und Interfaces

Transcrição

Prg08-Objekte und Interfaces
Programmieren 1
08 – Objekte und Interfaces
Bachelor Medieninformatik
Sommersemester 2015
Dipl.-Inform. Ilse Schmiedecke
[email protected]
Schmiedecke – Programmieren 1
1
Objektorientierung: Von Static zu Instance
 Klasse Novosketch bietet nur statische Methoden:
Schmiedecke – Programmieren 1
2
Statisch – nur ein Zeichenfeld
 Wenn alles statisch ist, dann gibt es genau eine Zeichenfläche
 Mit NovoSketch.drawLineTo(...) wird genau in diese
Zeichenfläche gemalt.
Schmiedecke – Programmieren 1
3
3
Statische Initialisierung
 Dadurch, dass die Klasse NovoSketch im Programm benutzt
(geladen) wird, wird sie initialisiert:
 die statischen Attribute werden initialisert
 der statische Initialisierer wird aufgerufen – die Zeichenfläche erscheint
Schmiedecke – Programmieren 1
4
We wäre es mit 2-3 Zeichenflächen?
Schmiedecke – Programmieren 1
5
Von Static nach Instance
Was muss sich ändern?
1. Alle Methoden müssen Instanzmethoden werden
2. Die statische Initialisierung muss durch einen Konstruktor
ersetzt werden
3. An der Aufrufstelle müssen die Novosketch-Instanzen erzeugt
und dann die Instanzmethoden aufgerufen werden
Schmiedecke – Programmieren 1
6
6
Konstruktion der Instanzen
1. Alle Methoden müssen Instanzmethoden werden

static entfernen
2. Konstruktor statt statischer Initialisierung

Index für die Position auf dem Bildschirm
Schmiedecke – Programmieren 1
7
7
Objektorientierung: Von Static zu Instance
 Die objektorientierte Klasse NovoSketch sieht ganz ähnlich aus:
Schmiedecke – Programmieren 1
8
8
Benutzung der Instanzen
 Zeichenfläche 2x instanziieren
 jeweils Titel und Startpunkt
setzen
 Zeichen auf 1. Zeichenfläche
 Zeichnen auf 2. Zeichenfläche
Schmiedecke – Programmieren 1
9
Zwei austauschbare Implementierungen
 2 NovoSketch-Implementierungen für X3 Etch-a-Sketch
 die "einfache" novosketch.NovoSketch mit "Macken" bei langen Linien
 die robustere canvassketch.NovoSketch
 austauschbar ohne Änderung Ihres Codes
 einfach beim Import entscheiden, welches Paket gewählt wird
 Instanzen können auch simultan existieren:
 der Rest bleibt unverändert
 Grund: alle Methodensignaturen sind gleich
Schmiedecke – Programmieren 1
10
10
Interfaces
 Die Methodensignatur beschreibt die äußere Form
einer Methode
 Um eine Methode zu (syntaktisch korrekt) zu
benutzen, braucht man nur die Signatur.
 Java erlaubt es, reine Signaturen zu definieren,
ohne Implementierung.
public void drawInRed();
 eine Sammlung solcher Signaturen heißt Interface
 ein Interface ist eine besondere Klasse
 Interfaces kann man nicht instanziieren
Schmiedecke – Programmieren 1
11
11
Das Interface SketchboardInterface
Schmiedecke – Programmieren 1
12
12
... Wir wechseln jetzt zu einem
einfacheren Beispiel
Schmiedecke – Programmieren 1
13
13
Beispiel String Interface
 Von der Klasse String kennen wir nur die Schnittstelle
 In Java kann man sie so definieren:
interface StringInterface
{
String toUpperCase();
String toLowerCase();
String trim();
int length();
char charAt(int pos);
int indexOf(char c);
// etc....
}
Schmiedecke – Programmieren 1
Das Interface
StringInterface
beschreibt die Dienste,
die der Typ String
anbietet.
14
String und StringInterface
 man kann sagen, die Klasse String implementiert das
Interface StringInterface
 das ist kein Exklusivrecht: eine andere Klasse, z.B.
Zeichenkette, kann dasselbe Interface
implementieren.
StringInterface
"implementiert"
String
"implementiert"
Sting und Zeichenkette
können auf dieselbe Art
benutzt werden, egal, wie
verschieden sie "innerlich"
sind.
Zeichenkette
Schmiedecke – Programmieren 1
15
Interfaces und Typen
 Eigentlich könnte man sagen, String und Zeichenkette haben
denselben Typ – schließlich verhalten sie sich identisch.
String string = "lalala";
Zeichenkette kette = "hahaha";
string = string.toUpperCase();
string = kette;
string = string.toUpperCase();
Typfehler!!!
 Java weiß nichts über ihre Gemeinsamkeit...
 Man kann es mitteilen:
class Zeichenkette implements StringInterface {...}
class String implements StringInterface {...}
String ist allerdings bereits
implementiert – nur Denkmodell -
Schmiedecke – Programmieren 1
16
Interfaces als Typen
class Zeichenkette implements StringInterface {...}
class MyString implements StringInterface {...}
MyString und Zeichenkette haben denselben Typ, also kann man ihre
Objekte jetzt derselben Variable zuweisen und identisch benutzen:
StringInterface irgendwas;
Zeichenkette kette;
MyString mystring;
irgendwas = kette;
irgendwas.toUpperCase();
irgendwas = mystring;
irgendwas.toUpperCase();
StringInterface
implementiert implementiert
MyString
Schmiedecke – Programmieren 1
Zeichenkette
17
Vertrag und Zulassung
 implements ist wie ein Türschild:
Dr.Frauke Wurzel
"Steuerberater" oder "Kieferorthopäde"
Kieferorthopädin
Alle Kassen
 Auch wer die Person nicht kennt,
weiß aufgrund des Schildes, welche
Max Geldhahn
Dienste er in Anspruch nehmen kann
Steuerberater
(und vertraut auf Kompetenz).
 Der Java-Compiler ist die Prüfbehörde:
Eine Klasse wird nur dann kompiliert, wenn sie alle ihre
implements-Behauptungen erfüllt (d.h. alle angegebenen
Methoden implementiert).
 Damit ist "implements" vertrauenswürdig...
Nico Roßberg
vereidigter Kfz-Sachverständiger
Schmiedecke – Programmieren 1
18
Beispiel Zähler
Das sollte jeder Zähler anbieten:
interface Zaehler
{
void zaehlen();
int wertLesen();
}
// Name des Interface
// Vertragsgegenstand: zählen
// Vertragsgegenstand: Wert lesen
Methodendeklaration
Methodensignatur:
(abstrakte Methodendeklaration)
void zaehlen ();
Rückgabetyp
Name der Methode
Parameterliste
Semikolon
(Implementierung)
void zaehlen()
{
// hier folgt der
// Algorithmus:
// "Methodenrumpf"
}
Schmiedecke – Programmieren 1
19
Zähler-Interface und 2 Implementierungen
interface Zaehler
{
void zaehlen();
int wertLesen();
}
class Basiszaehler implements Zaehler {
int wert = 0;
void zaehlen() { wert ++; }
int wertLesen() { return wert; }
}
class Countdownzaehler implements Zaehler {
int wert = 0;
void zaehlen() { wert --; }
int wertLesen() { return wert; }
void ssetzeStartwert (int startwert) {
wert = startwert;
}
}
Schmiedecke – Programmieren 1
zusätzliche Methode,
nicht vom Interface
gefordert
20
Zähler als Typ
Zaehler schrittzaehler = new Basiszaehler();
Zaehler rueckzaehler = new Countdownzaehler();
int strecke = schrittzaehler.wertLesen();
int rueckweg = rueckzaehler.wertLesen();
rueckzaehler.setzeStartwert(5000); // Typfehler
while
while (laufend)
(laufend)
{
schrittzaehler.zaehlen();
{
schrittzaehler.zaehlen();
rueckzaehler.zaehlen();
rueckzaehler.zaehlen();
// negative werte!
}
}
Schmiedecke – Programmieren 1
21
Zähler als Typ
Zaehler schrittzaehler;
Basiszaehler hinzaehler =
new Basiszaehler();
Countdownzaehler rueckzaehler =
new Countdownzaehler();
schrittzaehler = hinzaehler;
while (laufend) schrittzaehler.zaehlen();
rueckzaehler.setzeStartwert(schrittzaehler.wertLesen());
schrittzaehler = rueckzaehler;
while (laufend) schrittzaehler. zaehlen();
int schrittlaengenentwicklung = schrittzaehler.wertLesen();
// oder:
schrittlaengenentwicklung = rueckzaehler.wertLesen()
Schmiedecke – Programmieren 1
22
...und noch einmal: Typanpassung
 Basiszaehler und Countdownzaehler haben nicht
wirklich denselben Typ:
 Sie haben beide den Typ Zaehler,
d.h. die Typbeschreibung von Zaehler passt auf beide.
 Aber die Spezifikation von Countdownzaehler umfasst
eine Methode mehr als Zaehler!
Schmiedecke – Programmieren 1
23
Typanpassung



Countdownzaehler-Objekte können wie Zaehler benutzt werden:
Zaehler zaehler =
new Countdownzaehler();
zaehler.zaehlen();
Aber nicht jeder Zaehler kann, was Countdownzaehler können:
zaehler = new Basiszaehler();
zaehler.startwertSetzen(500); // undefiniert!
Bei der Zuweisung an eine Zaehler-Variable erfolgt eine implizite Typanpassung der Referenz
(nicht des Objekts)
Variable vom Typ Zaehler
Referenz vom Typ Zaehler

Objekt vom Typ
Countdownzaehler
Mit einer Referenz vom Typ Zaehler kann man nur Zaehler-Methoden rufen,
egal welches Objekt sie referiert.
Schmiedecke – Programmieren 1
24
Referenz-Typ als Aspekt
 Der Typ der Referenz entscheidet darüber, welcher (Teil-)Aspekt
eines Objektes sichtbar ist.
 Der Objekttyp wird nicht verändert!
Countdownzaehler down = new Countdownzaehler()
Zaehler zaehler = down;
down.startwertSetzen(100) // funktioniert
zaehler.startwertSetzen(100) // geht nicht
Variable vom
Typ Zaehler
Variable vom Typ
Countdownzaehler
Referenz vom
Typ Countdownzaehler
Referenz vom
Typ Zaehler
Objekt vom Typ
Countdownzaehler
Schmiedecke – Programmieren 1
25
Explizite Typanpassung
 Der Programmierer kann eine Zaehler-Referenz explizit an den Typ
Countdownzaehler anpassen, um sie als Countdownzaehler-Referenz
verwenden:
Zaehler zaehler =
new Countdownzaehler();
(Countdownzaehler)zaehler.
startwertSetzen();
 Die Anpassung geschieht "auf eigene Gefahr":
Ist das referierte Objekt nicht vom Typ Countdouwnzaehler, bricht das
Programm ab (Fehlermeldung: ClassCast Exception)
Variable vom
Typ Zaehler
Referenz angepasst an
Countdownzaehler
Objekt vom Typ
Zaehler
ClassCastException!
Schmiedecke – Programmieren 1
26
Objekttyp erfragen
 Zur Compilezeit ist (grundsätzlich) nicht entscheidbar, welchen genauen Typ
ein Objekt hat, das eine Variable referiert.
public class Typen {
public Zaehler zaehler;
public void ordneZaehlerZu(Zaehler z) {
zaehler = z;
}
}
 Zur Laufzeit kann dies erfragt werden durch den Operator instanceof
if (zaehler instanceof Countdownzaehler)
zaehler.startwertSetzen(500);
Schmiedecke – Programmieren 1
27
Zurück zu Etch-a-Sketch
Schmiedecke – Programmieren 1
28
28
Das Interface SketchboardInterface
Schmiedecke – Programmieren 1
29
29
Das Interface implementieren
 Beide Klassen implementieren das Interface SketchboardInterface
 Beide Klassen haben daher zusätzlich den Typ SketchboardInterface
 Instanzen beider Klassen können einer Variable vom Typ SketchboardInterface
zugewiesen werden.
Schmiedecke – Programmieren 1
30
SketchboardInterface als Variablentyp verwenden
 Beide Variablen haben jetzt den Typ SketchboardInterface
 Die Methoden des Interfaces sind damit aufrufbar.
 (Wie sie genau funktionieren, hängt vom Typ der Instanz ab, nicht vom Typ der Variable.)
Schmiedecke – Programmieren 1
31
Verwendung
 Durch ein Interface wird festgelegt werden, worauf sich
der Benutzer des Typs verlassen kann
 Gut für Teamwork:
 A implementiert das Interface
 B verwendet das Interface als Typ
 Gut für schnelle Prototypen
 Die erste Implementierung ist ein "Dummy"
 Dann folgt eine bessere Implementierung zum Testen
 Dann folgt die Produktivimplementierung
 Gut für Technologiewechsel
 Ersatztechnologie implementiert dasselbe Interface
 Wechsel ist unkompliziert
Schmiedecke – Programmieren 1
32
32
Interfaces sind einfach...
Nächstes Mal geht es um Vermeidung von
Doppelarbeit
Schmiedecke – Programmieren 1
33
33
Für Spezis: Die Zeichnung als Instanz
 main muss noch viel verwalten




die Zeichenflächen-Instanzen
die Titel der Zeichenflächen
die Koordinaten der jeweiligen Figur
das Malen der jeweiligen Figur
 Zeichnung als eigenständiges Objekt:




erzeugt ihre Zeichenfläche
setzt ihren eigenen Titel
verwaltet ihre eigenen Koordinaten
malt die Figur
Schmiedecke – Programmieren 1
34
die Zeichnung als Instanz
 main muss nur noch
 Zeichnungen
instanziieren
 für jede Zeichnung
draw() rufen
Schmiedecke – Programmieren 1
35
35

Documentos relacionados