Info B VL 3: Klassen und ihre Komponenten
Objektorientiere Programmierung in Java 2003
Ute Schmid (Vorlesung) Elmar Ludwig ( ¨ Ubung)
FB Mathematik/Informatik, Universit¨at Osnabr¨uck
Info B VL 3: Klassen und ihre Komponenten – p.50
Wdh: Komponenten von Klassen
Klassen können folgende Komponenten/Members enthalten
Felder
Methoden
(innere) Klassen (später)
Eine Komponente kann an die Klasse (static) oder an eine Instanz der Klasse gebunden sein.
Instanzmethoden können sich auf ihr aufrufendes
Objekt beziehen.
this (1)
a = c.area();
area() ist scheinbar parameterlos, aber die Methode hat einen impliziten Parameter this .
this hat als Wert die Referenz auf das Objekt, über das die Methode aufgerufen wurde.
this muss häufig nicht explizit angegeben werden:
Wenn eine Methode auf Komponenten zugreift, wird – wenn nichts anderes gesagt wird – angenommen, dass die Komponenten des aktuellen Objekts gemeint sind.
Info B VL 3: Klassen und ihre Komponenten – p.52
this (2)
this kann/sollte explizit angegeben werden, wenn man klar machen will, dass die Methode auf ihre eigenen Komponenten zugreift.
public double area(){
return Circle.PI * this.r * this.r; }
this wird explizit benötigt, wenn Parameter oder lokale Variablen einer Methode denselben Namen
haben wie Felder. Der Name wird zunächst auf lokale Grössen bezogen!
public void setRadius(double r) {
this.r = r; //Assign the argument r to the field this.r }
r = r ist sinnlos: weist Parameter r seinen eigenen Wert zu.
Klassen-Methoden können das this Schlüsselwort
Instanz- oder Klassenmethode?
Instanz-Methoden sind zentral für objekt-orientierten Programmierstil.
Dennoch kann es sinnvoll sein, Klassen-Methoden zu definieren.
Design-Entscheidung: Wenn häufig die Fläche eines Kreises berechnet werden soll, aber es ansonsten nicht notwendig ist, dafür extra ein Objekt der Klasse Circle zu erzeugen, sollte area() als
Klassen-Methode definiert werden.
Die Methode kann zweimal definiert sein (hier: einmal als Klassen-, einmal als Instanz-Methode).
Unterscheidung: verschiedene Signaturen!
public static double area(double r){
return PI * r * r;}
Info B VL 3: Klassen und ihre Komponenten – p.54
Beispiel bigger() (1)
Design-Entscheidung: Wie soll eine Methode realisiert werden, die den grösseren von zwei Kreisen
zurückliefert?
// Compare the implicit ‘this’ circle to the ‘that’ circle passed // explicitly as an argument and return the bigger one.
public Circle bigger(Circle that) { if(this.r > that.r) return this;
else return that;
} ...
Circle biggest = c.bigger(d); // Instance method:
// alternatively d.bigger(c)
Beispiel bigger() (2)
// Compare circle a to circle b and return // the one with the larger radius
public static Circle bigger(Circle a, Circle b) { if(a.r > b.r) return a;
else return b;
} ...
Circle biggest = Circle.bigger(x,y); // Static method
Info B VL 3: Klassen und ihre Komponenten – p.56
Referenztypen
Klassen (und Arrays) sind Referenztypen. Objekte haben einen bestimmten Typ:
Circle c = new Circle();
c ist ein Objekt vom Typ Circle int[] a =
1,2,3,4,5
;
a ist ein Array-Objekt String s = "Hello";
s ist ein String-Objekt
Array und String haben speziellen Status
Arrays/Strings
In der Object -Hierarchie findet sich keine Unterklasse Array
Es gibt potentiell unendlich viele Arrays
(Dimensionalität, Typ der Elemente). Wie bei der
Definition und Erzeugung anderer Objekte steht links der Typ des Arrays (Dimensionalität und Typ der
Elemente), aber nicht die Länge des Arrays! (siehe Vorlesung Informatik A)
int[] queens = new int[8];
default-mäßig mit 0en initialisiert
Für String kann ein Objekt direkt initialisiert werden:
Text vom Typ String (Zeichen in doppelten
Anführungszeichen) kann direkt an eine Variable vom Typ String zugewiesen werden.
String s = "This is an" +
"error message"; Info B VL 3: Klassen und ihre Komponenten – p.58
Referenzen (1)
Primitive Datentypen: feste, bei Deklaration bekannte Grösse (z. B. int bekommt 32 Bit)
Klassen und Arrays: zusammengesetzte Typen (composite types)
keine Standardgrösse angebbar
benötigen häufig mehr Speicherplatz
Manipulation by reference (aber: call by value
Parameterübergabe-Mechanismus!)
null Referenz: Referenz auf “Nichts”, Abwesenheit
einer Referenz; Wert null kann an jede Variable für
einen Referenztyp zugewiesen werden
Referenzen (2)
Referenz: fester Wert (Speicheradresse), der auf das Objekt verweist
Zuweisung eines Objekts an eine Variable: Variable hält Referenz auf dieses Objekt
Übergabe eines Objekts als Parameter: Methode erhält die Referenz, über die das Objekt manipuliert werden kann
Java erlaubt keine explizite Manipulation von Referenzen
Wichtiger Unterschied zwischen primitiven Datentypen und Referenztypen: Kopieren von Werten und Prüfung von Gleichheit
Info B VL 3: Klassen und ihre Komponenten – p.60
Kopieren von Werten vs. Referenzen
int x = 42;
int y = x;
Circle c = new Circle();
c.r = 2.0;
Circle d = c;
c d
2411 2412
4711 4711
4711 x
y
1124 1125
42 42
Object
r=2.0
Kopieren von Objekten (und Arrays)
Für die int-Variablen x und y existieren zwei Kopien des 32-bit Integers 42.
Variable d enthält eine Kopie der Referenz, die in Variable c steht. Man spricht hier auch von aliasing.
Achtung: Wenn zwei Referenzen a und b auf dasselbe Objekt zeigen, kann ein Methodenaufruf (z.B a.f() ) an das eine Objekt den Wert eines Feldes ändern
(“calling a method for its side effects”). Das Feld ist
dann beim Objekt geändert. Sowohl a.feld als auch b.feld liefern den aktuellen Wert!
Eine Kopie des Circle Objekts in der Java VM, aber zwei Kopien der Referenz auf dieses Objekt!
Info B VL 3: Klassen und ihre Komponenten – p.62
Beispiel ‘Circle’
Circle c = new Circle();
c.r = 2.0;
Circle d = c; // c and d refer to same object System.out.println(c.r); // Print out radius of c: 2.0 d.r = 4.0; // Change radius of d
System.out.println(c.r); // Print out radius of
// c again: 4.0
Clonen
Kopieren des Objektes selbst: clone()
Objekte müssen zu einer Klasse gehören, die als Cloneable deklariert ist (Implementieren des
Cloneable -Interfaces und der clone() -Methode) Arrays sind immer Cloneable
clone() erzeugt eine flache (“shallow”) Kopie: alle primitiven Werte und Referenzen werden kopiert. Das heisst, Referenzen werden nicht ge-cloned!
rekursives Kopieren muss explizit implementiert werden.
Casting ist notwendig: clone() liefert Object
Info B VL 3: Klassen und ihre Komponenten – p.64
Clonen von Arrays
int[] data = {1,2,3,4,5}; // An array
int[] copy = (int[]) data.clone(); // A copy of the array int[][] data = {{1,2,3},{4,5}}; // Array of 2 refs
int[][] copy = (int[][]) data.clone(); // Copy copy[1] = new int[]{7,8,9};
// this does not change data[1]
copy[0][0] = 99; // this changes data[0][0] too!
int[][] data = {{1,2,3},{4,5}}; // Array of 2 refs int[][] copy = new int[data.length][]; // new array
// to hold copied arrays
for (int i = 0; i < data.length; i++)
Illustration
1 2 3
1 2 3
4 5
4 5
data copy
7 8 9
0 1
0 1
data copy
int[][] copy = (int[][]) data.clone();
copy[1] = new int[] {7,8,9};
copy[0][]0]
Info B VL 3: Klassen und ihre Komponenten – p.66
Clonen von Objekten
Clonable Objekte müssen das (Marker) Interface Cloneable implementieren
und die in Object definierte clone() Methode überschreiben
(Vorgriff auf spätere Kapitel)
CloneCircle e = new CloneCircle();
e.r = 3.0;
CloneCircle f = (CloneCircle) e.clone(); // copy object
System.out.println("Do circles e and f have the same reference? ");
if (e == f)
System.out.println("yes");
else System.out.println("no"); // no, they do not!
f.r = 5.0; // only changes r in f
System.out.println(e.r); // still 3.0
Gleichheit von Objekten (und Arrays)
== Operator bei primitiven Typen: Prüfung auf selben Wert (bei ganzzahligen Werten: gleiche Bits)
== Operator bei Referenztypen: Prüfung, ob zwei Referenzen auf dasselbe Objekt verweisen,
aber nicht, ob zwei Objekte denselben Inhalt haben!
Prüfung der Gleichheit von Inhalten von Objekten:
equals()
Methode ist in Object definiert (default ist == )