Object - TU Darmstadt

Werbung
Grundzüge der Informatik
V10. Objektorientiere Konzepte
in Java
Prof. Dr. Max Mühlhäuser
FG Telekooperation
TU-Darmstadt
Agenda
• Die Wurzelklasse "Object"
• Wrapper-Klassen: eine Brücke zwischen
Primitiven und Referenztypen
• Objekterzeugung: Initialisierung mit
Konstruktoren
• Überladen von Methoden
• Schnittstellen
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
2
Die Klasse Object
• java.lang.Object ist die Superklasse aller Java-Klassen
– Object selbst besitzt – als einzige Java-Klasse – keine Superklasse
– Object ist die Wurzelklasse der Java-Klassenhierarchie
• Jede Java-Klasse, bei deren Deklaration der extends-Teil
nicht angegeben wird, ist automatisch eine direkte Unterklasse
von Object
• Daraus folgt
– jede Java-Klasse erbt – direkt oder indirekt – alle Methoden von
Object
– In einer Variable des Typs Object können beliebige Objekte
gespeichert werden – praktisch um Listen und andere
Datenstrukturen allgemein zu programmieren (siehe später V15:
Datenstrukturen)
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
3
Vordefinierte Methoden in Object
• In Object vordefinierte Methoden sind in allen anderen
Objekten auch definiert Æ Verwendung bei jedem Typ möglich
• Die wichtigsten vordefinierten Methoden sind bereits bekannt
– boolean equals(Object o) – Objektvergleich
– String toString() – Gibt die String-Repräsentation des
Objekts zurück
• Weitere vordefinierte Methoden für fortgeschrittene
Programmierkonzepte (Threadsynchronisation, Hashtables,
etc.)
• Grundfunktionalität der vordefinierten Methoden vorhanden,
aber sehr allgemein Æ Überschreiben meist sehr sinnvoll
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
4
Wrapper-Klassen
• Primitive Datentypen (int, boolean, etc.) sind
keine Klassen
Æ sind nicht von Object abgeleitet, haben keine Methoden
Æ können nicht an Variablen des Typs Object zugewiesen
werden
• Zuweisung zu Object manchmal wünschenswert Æ
Wrapper-Klassen (Hüllklassen)
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
5
Wrapper-Klassen
Verwendung von Wrapper-Klassen
• Name: meist wie primitiver Datentyp, aber Anfangsbuchstabe
großgeschrieben; Package java.lang
– java.lang.Byte, java.lang.Short,
java.lang.Integer, java.lang.Long,
java.lang.Float, java.lang.Double,
java.lang.Character
• Objekte sind immutable
– Wert-Zuweisung über Konstruktor
– Wertabfrage über <primitive-Type>Value()
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
6
Wrapper-Klassen
Object
Object
• Unschön: int und Integer sind bei
Zuweisung nicht konform. Das gleiche gilt
für die anderen Typen auch.
Number
int i = 5;
Number
Integer iobj = new Integer();
iobj = i; // Error !
Integer
int
Integer
int
i = iobj; // Error !
// Konversion per Konstruktor Konstruktor
iobj = new Integer(i);
// oder Konvertierungsmethode intValue()
i = iobj.intValue();
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
7
Casting
• Erinnern Sie sich? (V.3)
– b akzeptiert alle Roboter der Klassen B und C und deren
Erben (Transitivität der Relation)
A
– b akzeptiert Methoden die A und B anbieten
B
– b akzeptiert keine Methoden, die in C, aber nicht in A oder
B sind
• Was ist mit damit:
B b = new C();
b.methodDefinedInC();
C
– Funktioniert nicht, weil b keine Methoden aus C akzeptiert
• Aber: wir wissen, dass in b ein Objekts von Typ C
gespeichert ist
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
8
Casting
• Zuweisung an Subtypen möglich über Casting
• Syntax:
<Cast> ::= (<Type>)<Object-Expression>
• Bedeutung: „Nimm das Objekt und behandle es, als sei es vom Typ
<Type>“
• Falls das Objekt nicht in den angegebenen Typ umgewandelt werden
kann, tritt ein Laufzeitfehler auf (ClassCastException)
• Beispiel
B b = new C();
C c =(C)b;
// Funktioniert
c.methodDefinedInC(); // Funktioniert
b = new B();
c = (C)b;
12. 12. 2002 © MM ...
// erzeugt Laufzeitfehler, da b nicht vom Typ C
GDI - OO-Konzepte in Java
9
Der instanceof Operator
• Wie kann man testen ob ein Cast funktioniert?
• Lösung: Abfrage des dynamischen Typs einer Variable mit
instanceof
• Syntax:
<Instance-Of> ::= <Object-Expression> instanceof <Type>
• instanceof ergibt true, wenn <Object-Expression> an eine
Variable des Typs <Type> zugewiesen werden kann
– Ausnahme: Ist <Object-Expression> == null, so liefert
instanceof immer false
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
10
Der instanceof Operator
Beispiel
public class InstanceOfExample {
// Die Klassen A, B, C existieren wie auf S. 8 angegeben
public static void printCompatibility(A obj) {
if(obj instanceof C) {
System.out.println("obj ist vom Typ C");
}
if(obj instanceof B) {
System.out.println("obj ist vom Typ B");
}
if(obj instanceof A) {
System.out.println("obj ist vom Typ A");
}
// ...
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
11
Der instanceof Operator
// ...
public static void main(String[] args) {
printCompatibility(new A());
// Ergebnis:
// obj ist vom Typ A
printCompatibility(new B());
// Ergebnis:
// obj ist vom Typ B
// obj ist vom Typ A
printCompatibility(new C());
// Ergebnis:
// obj ist vom Typ C
// obj ist vom Typ B
// obj ist vom Typ A
}
}
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
12
Objektinitialisierung mit Konstruktoren
• Bei der Definition einer Klasse können Konstruktoren
deklariert werden.
• Konstruktoren werden für Initialisierungen der
Attribute mit Werten benutzt, wenn der konkrete
Wert erst zum Zeitpunkt der Objekterzeugung und
nicht bereits bei der Übersetzung der
Klassendefinition bekannt ist
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
13
Objektinitialisierung mit Konstruktoren
• Eine Klassendefinition kann beliebig viele Konstruktoren
enthalten (stellt verschiedene Initialisierungs-Vorschriften zur
Verfügung) Æ explizite Konstruktoren
• Falls kein Konstruktor explizit deklariert wird, wird ein
parameterloser Konstruktor automatisch generiert
• Alle Konstruktoren haben den gleichen Namen Æ Klassenname
– unterscheiden sich nur in der Anzahl und Typ der Parameter
– Überladung der Konstruktoren
• Im Gegensatz zu Methoden haben Konstruktoren keinen
Rückgabetyp
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
14
Objektinitialisierung mit Konstruktoren
• Syntax
<Constructor> ::= <Modifier> <Class-Name>
(<Parameter-List>) <Throws-Clause> {
<Statements>
}
<Parameter-List> ::= <Parameter> | <Parameter> ,
<Parameter-List>
<Parameter> ::= <Type> <Identifier>
< Throws-Clause> : kommt später, vorerst ε
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
15
Objektinitialisierung mit Konstruktoren
Beispiel: Kreis
• Ein Kreis ist durch die Koordinaten des Ursprungs (x,
y) und einen Radius definiert :
ohne Konstruktor sind die
Anfangswerte 0
class Circle {
double x, y, radius;
Circle(double xx, double yy, double rr){
x = xx;
y = yy;
Initialisierung der
radius = rr;
Attributwerte beim Erzeugen
}
eines Kreis-Objektes
double perimeter() { ... }
double area() { ... }
}
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
16
Objektinitialisierung mit Konstruktoren
Beispiel: Kreis
class Display {
// Kreise werden immer relativ zu
// ( 0.0, 0.0 ) erzeugt
Circle k = new Circle(2.5);
Was passiert beim
Übersetzen dieser
Klasse?
// also geben wir beim Erzeugen
// nur den Radius an
Circle k2 = new Circle(); // oder nichts
k2.r = 1.0; // und setzen Radius später
...
Mit der jetzigen
Implementierung ist Circle()
nicht erlaubt Æ Fehler
}
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
17
Objektinitialisierung mit Konstruktoren
Beispiel: Kreis
• Werden verschiedene Initialisierungsvorschriften für
Kreise benötigt, dann müssen verschiedene
überladene Konstruktoren in der Klasse Kreis
implementiert werden
– Circle(double xx, double yy, double rr)
– Circle(double rr)
– Circle()
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
18
Überladen der Konstruktoren
Beispiel: Kreis
class Circle {
double x, y, r;
Circle(double xx, double yy, double rr) {
x = xx; y = yy; r = rr; }
Circle(double rr) { r = rr; }
Circle() { }
Nur dann automatisch eingefügt, wenn
kein Konstruktor explizit definiert wird
double perimeter() {return ...; }
double area() { return ...; }
}
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
19
Aufruf eines anderen Konstruktors der
selben Klasse
class Circle {
double x, y, r;
Circle(double xx,
Alternative: den eigenen Konstruktor
mithilfe von this() aufrufen
double yy, double rr) {
x = xx; y = yy; r = rr; }
Circle(double rr) {
this(0.0, 0.0, rr);
}
Circle() { this(0.0, 0.0, 1.0); }
double perimeter() { ... ; }
double area() { ... ; }
}
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
20
Aufruf eines anderen Konstruktors
• Der Aufruf eines anderen Konstruktors muss die erste
Anweisung des Konstruktors sein
– Daher ist innerhalb eines Konstruktors nur maximal ein weiterer
Konstruktoraufruf möglich
– Ein anderer Konstruktor der eigenen Klasse kann über
this(<Parameter-List>) aufgerufen werden
– Ein Konstruktor einer Superklasse kann über super(<ParameterList>) aufgerufen werden
• Welche der Konstruktorvarianten innerhalb eines expliziten
Aufrufs tatsächlich verwendet wird, wird über die
Parameteranzahl bzw. die Parametertypen spezifiziert
• Der aufgerufene Konstruktor darf selbst wieder einen weiteren
Konstruktor aufrufen
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
21
Konstruktoren und Automatismen
• Wird in einem Konstruktor kein anderer Konstruktor
explizit aufgerufen, ist dies äquivalent zu
super(); am Beginn des Konstruktors
• Wird kein Konstruktor deklariert, so erzeugt Java
automatisch
– Einen parameterlosen Konstruktor, der super() aufruft
Æ Enthält die Basisklasse keinen parameterlosen
Konstruktor, so schlagen die Automatismen fehl
– In diesem Fall muss ein anderer Konstruktor von Hand
aufgerufen werden
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
22
Überladen von Methoden
• Konstruktoren werden in Java überladen
– alle Konstruktoren einer Klasse haben den
gleichen Namen im gleichen Namensraum...
– ... aber unterschiedliche Signaturen Æ
unterschiedliche formale Argumenttypen und
-anzahl
• Nicht nur Konstruktoren können überladen
werden, sondern auch beliebige (geerbte
oder eigene) Methoden
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
23
Beispiel
Überladen von Methoden
class SimplePrinter {
void print( int i ) { .. };
}
class Printer extends SimplePrinter
void print(int i) { .. };
int print(int i) { .. };
void print(boolean i) { .. };
}
{
FEHLER!
Überschreibung nur mit identischer
Signatur möglich
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
24
Überladen von Methoden
• Überschreibung bei Vererbung: Eine Methode kann in einer
Unterklasse mit dem gleichen Namen und Signatur wie eine
Methode in der Superklasse definiert werden
• Eine Methode kann gleichzeitig überladen und überschrieben
werden:
– in der Unterklasse kann die überschriebene Methode als
super.methodenName() bzw. der überladene
Konstruktor der Superklasse als super() aufgerufen
werden
• Beim Überladen wird der Rückgabetyp nicht zur
Unterscheidung von Methoden herangezogen
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
25
"Ad hoc" Polymorphie
Signatur: void methode(Object)
Die Methodennamen sind überladen. Die
Unterscheidung basiert auf Parametertypen bzw.
Anzahl
Der Compiler erkennt die Typen und wählt die
Methode statisch aus (compile time binding)
12. 12. 2002 © MM ...
void methode(Object o) { ... }
void methode(Person p) { ... }
static void main( .. ) {
Object p=Person();
methode(p);
GDI - OO-Konzepte in Java
26
Polymorphismus und OOP
• Monomorphe Sprachen (Typsysteme): es wird strikt ein Typ für
jede Programmeinheit definiert (z.B. Pascal)
• Polymorphie („Vielgestaltigkeit“): Eine Programmeinheit kann
verschiedene Typen haben und somit verschiedene
Eigenschaften während der Laufzeit
Polymorphie
ad-hoc
universal
overloading
coercion
parametric
inclusion
Überladung
Typkonversion
Generizität
Vererbung
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
27
Polymorphie und OOP
• Überladung: Verschiedene Methoden haben den gleichen Namen (z.B.
equals für verschiedene Typen)
• Typkonversion/Casting: Umwandlung des Typs eines Wertes (z.B.
(int)2.5)
• Generizität: Typvariablen müssen zunächst einen Typ erhalten bevor
ein Typ oder eine Methode benutzt werden kann (z.B. Arraytyp)
• Vererbung: Variablen haben neben einem statischen Typ auch einen
dynamischen, der vom Typ des referenzierten Objekts abhängt
–
Der dynamische Typ bestimmt welche Implementierung (innerhalb einer
Vererbungshierachie) einer Methode bei einem Aufruf zur Anwendung
kommt
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
28
Schnittstellen
• Schnittstellen (Interfaces) definieren Dienstleistungen für
andere Klassen, ohne etwas über die Implementierung der
Dienstleistungen festzulegen
– bestehen nur aus Methodensignaturen sowie
Konstantendefinitionen
• stellen funktionale Abstraktionen bereit, die das „Was“, aber
nicht das „Wie“ festlegen
UML Notation
<<interface>>
public interface anInterface {
AnInterface
method()
12. 12. 2002 © MM ...
public void method();
}
GDI - OO-Konzepte in Java
29
Schnittstellen
• Analog wie Variablen vom Klassentyp, können auch Variablen
vom Schnittstellentyp deklariert werden:
<Reference-Type> ::= <Class-Name> |
<Interface-Name> |
<Array-Type>
// in der Klasse anInterfaceClient
AnInterface anObject;
anObject.method(); // OK
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
30
Schnittstellen
• Die Implementierung der abstrakten Methoden erfolgt durch
Java-Klassen
• Wenn eine Klasse eine Schnittstelle implementiert, dann muss
sie alle Methoden der Schnittstelle implementieren. Auch leere
Implementierungen sind erlaubt, z.B. durch „{}“
implements AnInterface {
<<interface>>
AnInterface
method()
public void method() {
}
Empty
Implementation
}
UML Notation
für implements
class EmptyImplementation
method()
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
31
Schnittstellen
• Verschiedene Java-Klassen können dieselbe
Schnittstelle auf unterschiedliche Weise
implementieren
• Die Definition der Klienten-Klasse der Schnittstelle
kann ohne Änderung in Objekten aller
Implementierungsklassen wiederverwendet werden,
da sie nur die Schnittstelle anspricht und diese
unverändert bleibt
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
32
Schnittstellen
Aufrufende Klasse
Aufruf
<<interface>>
Schnittstelle
Schnittstelle wird
implementiert von
Klasse 1
Klasse1
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
Schnittstelle wird
implementiert von
Klasse 2
Klasse2
33
Schnittstellen
Verwendungsbeispiel
• Alle geometrischen Figuren verstehen die Nachricht paint(),
in der sie ihre spezifische Form zeichnen.
• Die Tatsache, dass alle geometrischen Figuren sich zeichnen
können, spiegelt sich in der Präsenz der nicht implementierten
(abstrakten) Methode paint() in der Schnittstelle
ShapeDisplay wieder
• Alle konkreten Klassen für geometrische Figuren (Circle, Line,
...) implementieren die Schnittstelle ShapeDisplay
– Jede dieser Klassen implementiert die Methode paint() in
einer spezifischen Weise: Ein Rechteck verwendet ein anderes
Verfahren, um sich zu zeichnen, als ein Kreis
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
34
Schnittstellen
Verwendungsbeispiel
<<interface>>
ShapeDisplay
void paint()
Schnittstelle wird
von Line
implementiert
Schnittstelle wird
von Circle
implementiert
12. 12. 2002 © MM ...
Circle
Line
void paint()
void paint()
GDI - OO-Konzepte in Java
35
Schnittstellen
Verwendungsbeispiel
• Die Klasse Display verwaltet eine Liste von geometrischen
Figuren, welche unterschiedlichen Typs sein können (Kreise,
Linien, ...)
• Wenn der Benutzer einen bestimmten Button drückt, werden
alle Elemente der Liste aufgefordert, sich zu zeichnen, indem
die Methode paint() an jedes Element vorgenommen wird
• Für Display ist der konkrete Typ der einzelnen Elemente der
Liste irrelevant. Alles was Display interessiert ist, dass alle
Elemente der Liste die Schnittstelle ShapeDisplay
implementieren
Æ die Methode paint() (auf ihre Weise) ausführen können
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
36
Verwendungsbeispiel
Display
paintAll()
12. 12. 2002 © MM ...
Schnittstellen
paint()
<<interface>>
ShapeDisplay
void paint()
Circle
Line
void paint()
void paint()
GDI - OO-Konzepte in Java
37
Schnittstellen
class Display {
ee
t
t
ejekk
j
OObb
llele
l
aa
e
nne
h
cich
i
ZZee
ShapeDisplay[] shapes;
...
public void paintAll() {
...
}
}
Starte
Starte mit
mit dem
dem ersten
ersten Feldelement
Feldelement und
und solange
solange das
das letzte
letzte
Element
Element noch
noch nicht
nicht erreicht
erreicht ist,
ist, verfahre
verfahre wie
wie folgt:
folgt:
•• sende
sende der
der Figur,
Figur, auf
auf welche
welche der
der aktuelle
aktuelle Verweis
Verweis liste[i]
liste[i]
zeigt,
zeigt, die
die Nachricht
Nachricht paint()
paint()
•• fahre
fahre mit
mit dem
dem nächsten
nächsten Element
Element fort
fort
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
38
Schnittstellen
Verwendungsbeispiel
class Display {
private ShapeDisplay[] shapes;
public Display(ShapeDisplay[] gsList) {
shapes = gsList;
}
public void paintAll() {
for(int i = 0; i < shapes.length; i++) {
if(shapes[i] != null) {
shapes[i].paint();
}
}
}
}
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
39
Schnittstellen
Verwendungsbeispiel
ttee
k
eek
j
j
OObb
llele
l
aa
e
nne
h
cich
i
ZZee
• Das übergeordnete
Zeichenverfahren paintAll()
kann spezifiziert werden, ohne
die aktuellen Typen der Figuren
zu kennen
• Man kann neue Typen von
geometrischen Figuren später
implementieren
• Man kann Exemplare von später erzeugten Typen in der Liste
hinzufügen, ohne das Zeichenverfahren von paintAll() anpassen zu
müssen
• Der Dienstabnehmer (Display) ist unabhängig vom Dienstanbieter (die
konkreten ShapeDisplay Klassen).
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
40
Java: Syntax und Semantik
• Eine Klasse kann nur eine direkte Superklasse besitzen
(Einfachvererbung)
• Aber: Eine Klasse kann mehrere Schnittstellen implementieren
(eine Art Mehrfachvererbung)
• Methoden, die eine Schnittstellen-Methode implementieren,
müssen public sein
• Typ-Signatur der implementierenden Methode Ù
Typ-Signatur, die in der Schnittstellen-Definition spezifiziert
ist
• Klassen, die Schnittstellen implementieren, können eigene
zusätzliche Methoden definieren
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
41
Konstanten in Schnittstellen
• Durch die Deklaration von Konstanten in
Schnittstellen kann sichergestellt werden, dass
spezielle konstante Werte überall konsistent zur
Anwendung kommen
• Es handelt sich um öffentliche (public) konstante
Klassenattribute
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
42
Konstante in Schnittstellen
interface Bildschirmformate {
final int X_VGA = 600, Y_VGA = 480;
final int X_SVGA = 800, Y_SVGA = 600; ...
}
class Fenster {
if(bildschirmformat ==
Bildschirmformate.VGA)
setSize(Bildschirmformate.X_VGA,
Bildschirmformate.Y_VGA);
else ...
}
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
43
Schnittstellen und
Vererbung
• Jede Schnittstelle kann von einer oder
mehreren Oberschnittstellen erben
(Schlüsselwort extends)
• Wenn eine Klasse eine Schnittstelle2
implementiert, die Erbe einer
Schnittstelle1 ist, muss die Klasse alle
Methoden implementieren, die in der
Schnittstellenvererbungskette definiert
sind
12. 12. 2002 © MM ...
GDI - OO-Konzepte in Java
<<interface>>
Schnittstelle1
method1();
method2();
<<interface>>
Schnittstelle2
method3();
MyClass
44
Herunterladen