Sie sind auf Seite 1von 34

Klassen und Objekte

Beispiel Punkte auf der Ebene


Modellierung:
Mathematisch (x, y), x,y R
In Java: zwei Variablen x, y vom Typ double.
Beispiel Datum
Wichtige Daten: Tag, Monat, Jahr
Mögliche Modellierung: Drei Variablen int day, String month (oder int month) , int
year.
Beispiel Telefoneintrag
String name, phone

Wichtig:
• Nicht alle Daten des Objekts werden modelliert!
• Was will man mit den Objekten machen

Tran / Hettel GDI 2 1


Klassen und Objekte

Mehrere Punkte
Eine Möglichkeit: Mehre Variablen etwa x1, x2, ..., x100, y1, y2, ...,
y100.
Problem: Beziehungen der Variablen unklar (Verletzung des Prinzips der Nähe).

Konzept von Klassen


Eine Klasse stellt einen Plan oder ein Muster dar, das eine beliebige Anzahl
gleichartiger Objekte (mit äquivalentem Zustand und Verhalten) beschreibt.
In dem Muster stehen:
Daten zur Beschreibung des Objekts.
Befehle, die man an das Objekt versenden kann.
Eine Klasse hat in der Regel nur einen Plan zur Herstellung der Objekte.

Tran / Hettel GDI 2 2


Klassen und Objekte

1. Versuch
In Point.java
public class Point Attribute x,y existieren
{
public double x;
nur mit einem Objekt.
public double y;
}

In der Anwendung
Point p1, p2; // zwei Namen deklariert
p1 = new Point(); // Objekte müssen erzeugt werden
p1.x = 1; // OK
p2.x = 1; // Fehler –
// Es gibt kein Objekt namens p2

Problem: Das "Geheimnisprinzip" wird verletzt.

Tran / Hettel GDI 2 3


Klassen und Objekte

➔ Jede Änderung der Klasse Point kann dazu führen, dass an vielen Stellen
angepasst werden muss.
➔ Geheimnisprinzip: Jedes Objekt hat eine klar definierte Vereinbarung, die
festlegt, welche Operationen mit ihm erlaubt sind (WAS können wir mit dem
Objekt tun). Der Zustand des Objekts (Gedächtnis des Objekts - beschrieben
durch die Daten) ist gekapselt (Datenkapselung), so dass ein Zugriff von
außerhalb nicht möglich ist.
➔ Zugriffsrechte in Java gesteuert durch die Angaben:
− public: Für alle sichtbar.
− private: Nur innerhalb der Klasse.
− protected: Innerhalb der Klasse, abgeleitete Klassen (siehe später) und alle
Klassen in dem selben Verzeichnis (Paket).
− default (keine Angabe): Sichtbar für alle Klassen in dem selben Verzeichnis
(Paket).

Tran / Hettel GDI 2 4


Klassen und Objekte

2. Versuch
Mit Hilfe von Klassenmethoden

public class Point


{
private double x; das zu ändernde Objekt muss übergeben werden
private double y;
public static void setX(Point THIS, double x)
{
THIS.x = x; Zugriff auf Daten von THIS möglich,
} da innerhalb der Klasse
public static double getX(Point THIS)
{
return THIS.x;
}
...
}

Tran / Hettel GDI 2 5


Klassen und Objekte

Anwendung
Point p = new Point();
Point.setX(p, 5);

Unschön:
− Schreibarbeit.
− Beziehung zu Objekt nicht klar (wer ist der Nachrichtenempfänger?).
Der Compiler soll uns die Schreibarbeit abnehmen.
Prägnante Schreibweise wie p.setX(5);
Nachricht / Befehl wird an das Objekt p gesendet.
➔ Konzept von Instanz- / Objektmethoden

Tran / Hettel GDI 2 6


Klassen und Objekte

public class Point


{
private double x;
private double y;

public void setX(double x)


{
this.x = x;
}
public double getX()
{ Es wird implizit eine „versteckte“
return this.x; Referenz namens this auf das zu
}
... übergebende Objekt generiert
}

Für Daten eines Objekts verwendet man zum Beispiel unter Android auch den
Präfix m (für Member).

Tran / Hettel GDI 2 7


Klassen und Objekte

− Objektmethoden haben keine static-Angabe.


− Objektmethoden können nur mit einem existierenden Objekt aufgerufen
werden.

Grobe Syntax einer Methodendeklaration

Type Identifier ( FormalParamList )


public
private
protected
static { Statement }
abstract
usw. Throws ;

Tran / Hettel GDI 2 8


Klassen und Objekte

Objektinitialisierung
1. Möglichkeit: Wie bisher. Objekte werden erzeugt und Daten werden gesetzt.
Umständlich, fehleranfällig.
2. Möglichkeit: Eine Klassenmethode schreiben wie etwa:
public static Point getInstance(double x, double y)
{
Point tmp = new Point();
tmp.x = x;
tmp.y = y;
return tmp;
}

Es gibt auch damit sinnvolle Anwendungen (➔ zum Beispiel das Einzelexemplar-


Muster - Singleton Pattern).
3. Möglichkeit: Konstruktoren
Konstruktoren sind spezielle Methoden (eigentlich Klassenmethoden), die Objekte
einer Klasse initialisieren.

Tran / Hettel GDI 2 9


Klassen und Objekte

Wichtig
• Der Name eines Konstruktors ist dem Namen der Klasse identisch.
• Es gibt keinen expliziten Rückgabewert (sonst ist es eine normale Methode!).
• Durch den new-Operator wird dynamisch der Speicher für ein Objekt der Klasse
bereitgestellt. Die entsprechende Konstruktormethode wird anschließend
aufgerufen, um den Speicher zu initialisieren.
• Wird kein Konstruktor deklariert/geschrieben, fügt der Compiler automatisch
einen Standardkonstruktor (Konstruktor ohne Parameter) hinzu. Attribute des
neuen Objekts haben dann nur Standardwerte (0, false bzw. null).
• Wird ein Konstruktor deklariert, fügt der Compiler keinen Standardkonstruktor
hinzu!
• Wollen wir mehrere Konstruktoren anbieten, so müssen wir die Konstruktoren
überladen.

Tran / Hettel GDI 2 10


Klassen und Objekte

Beispiel

public class Point


{
private double x;
private double y;
public Point()
{
// x und y haben Defaultwerte
}
public Point(double x, double y)
{
this.x = x; // this-Angabe darf entfallen, wenn der
this.y = y; // Name der Variable eindeutig ist. Hier nicht der Fall
}
...
}

Tran / Hettel GDI 2 11


Klassen und Objekte

Point p = new Point(1,2);


• Anlegen der Variablen p
p
• new
x 0.0
y 0.0

• Konstruktor
x 1.0
y 2.0

• Zuweisung (der Compiler kann die Zuweisung vorher durchführen!)


p
x 1.0
y 2.0

Tran / Hettel GDI 2 12


Klassen und Objekte

This-Anweisung (Konstruktordelegation)
Frage: Wenn Konstruktoren Methoden sind, darf man sie aufrufen?
Antwort: Nur von Konstruktoren heraus mit einer speziellen Syntax:
this(Parameterliste);

this(...) muss die erste Anweisung im Konstruktor sein.


public class Circle {
private double x, y, r;
public Circle() {
this(0,0,0);
// weitere Anweisungen dürfen folgen
}
public Circle (double x, double y, double r) {
this.x = x; this.y = y; this.r = r;
}
...
}

Tran / Hettel GDI 2 13


Klassen und Objekte

Objektausgabe Point p = new Point(1,2);


Versuch System.out.println(p);

// Ausgabe etwa: Point@...


Grund: JVM weiß nicht, wie sie ein Objekt ausgibt (sie kann es nicht wissen).
Eigentlich wird bei der Ausgabe jedes auszugebende Objekt gefragt:
System.out.println(p.toString());
Es wird eine Anfrage an das Objekt gesendet, um seine Darstellung als
Zeichenkette zu erhalten. Standard-Implementierung von toString ist die Ausgabe
von Klassenname@Hashcode
➔ toString –Methode neu implementieren (überschreiben).
(richtiger) Versuch: Methode toString implementieren:

public String toString()


{
return "(" + x + "," + y + ")";
} // Ausgabe z.B. (1.0,2.0)

Tran / Hettel GDI 2 14


Klassen und Objekte

Punkt verschieben
Möglichkeit: Über setter- und getter-Methoden:
p.setX(p.getX() + 3);
p.setY(p.getY() + 5);

Schlecht!! Die Logik liegt beim Anwender. Er muss viel über die benutzten
Objekte wissen. Das Objekt soll nicht nur Daten kapseln, sondern auch
geeignete (sinnvolle) Methoden anbieten. Das Was ist für den Anwender wichtig,
nicht das Wie.
Möglichkeit: Instanzmethode (Objektmethode)
public void move(double dx, double dy)
{
this.x += dx;
this.y += dY;
// evtl. weitere Schritte etwa Benachrichtigung
// eines anderen Objekts zum Neuzeichnen
}

Tran / Hettel GDI 2 15


Klassen und Objekte

Objekte vergleichen
1. Möglichkeit: Operator ==
Nur Identitätsvergleich! Häufige Anwendung
if (p == null) // gibt es hinter dem Namen p ein Objekt?

2. Möglichkeit: Eine Klassenmethode definieren.


public static boolean isEqual(Point p1, Point p2)
{
if (p1 == p2) { return true; }
else if (p1 == null || p2 == null) {
return false;
}
else {
return p1.x == p2.x && p1.y == p2.y;
}
}

Tran / Hettel GDI 2 16


Klassen und Objekte

3. Möglichkeit: Methode equals neu implementieren. Man beachte die Signatur


der Methode!

public boolean equals(Object obj)


{
if (obj instanceof Point == false)
// auch: obj == null || obj.getClass() != this.getClass()
{ // das zu vergleichende Obj ist kein Point-Objekt
return false;
}
else
{
// Typinformation wiedergewinnen
Point p = (Point) obj;
// und die Daten vergleichen
return this.x == p.x && this.y == p.y;
}
}

Tran / Hettel GDI 2 17


Klassen und Objekte

Methodenüberladung
Ein Methodenname wird mehrfach verwendet. Die Methoden müssen
verschiedene Signaturen haben. Der Rückgabetyp, Schlüsselwörter wie abstract,
final und Zugriffsmodifikatoren wie public, private usw. werden dabei nicht
berücksichtigt.
Beispiel
Erlaubt
public void translate(double x, double y) { ... }
public void translate(Point p) { ... }
public void calc(double x, int y) { ... }
public void calc(int x, double y) { ... }
//Problem: obj.calc(1,2) => Übersetzungsfehler

Nicht erlaubt public bool check() { ... }


void check() { ... }

Tran / Hettel GDI 2 18


Klassen und Objekte

Beachte: Es gilt ggf. die implizite Typerweiterung.


Beispiel
public void m(float f)
{
...
}
public void m(double d)
{
...
}
...
long l = 123;
m(l); // welche wird aufgerufen ?
m(2.0); // welche ?

Zur Wiederholung:
byte → short → int → long → float → double, char → int

Tran / Hettel GDI 2 19


Klassen und Objekte

Methode hashCode
Die Hash-Funktion ordnet jedem Objekt einen Wert zu.
Die hashCode-Methode soll einen int-Wert zurückliefern, der
− wiederholbar ist. D.h. obj.hashCode() muss bei erneutem Aufruf den selben
Wert zurückliefern, falls obj nicht verändert wurde.
− konsistent ist:
obj1.equals(obj2) → obj1.hashCode()== obj2.hashCode()
Falls obj1.hashCode()== obj2.hashCode() gilt, ist nicht unbedingt obj1.equals(obj2)
Eine gute Hash-Funktion ist normalerweise surjektiv. Die Wahrscheinlichkeit, dass
verschiedene Objekte den gleichen Hashcode haben, soll klein sein.
Standardimplementierung in JDK: Maschinenadresse des Objekts ➔ hashCode -
Methode muss implementiert werden, wenn die Objekte durch Hash-
Funktionen verglichen werden (Hash-Tabelle, Hash-Tree, Hash-Map usw.)
Praxistip: Lassen Sie Eclipse den Code dafür generieren.

Tran / Hettel GDI 2 20


Klassen und Objekte

Beispiel

public class Person


{
private String name, vorname;
private int tag, monat, jahr;
...
public int hashCode()
{
int a = tag + monat*12 + jahr;
return a*17*17 + name.hashCode()*17 + vorname.hashCode();
}
}

Tran / Hettel GDI 2 21


Klassen und Objekte

Objektzerstörung
Ein Objekt wird Müll, wenn es nicht mehr referenziert wird.
A a = new A();
...
a = null; // Das Objekt ist nun Müll

Der Müllsammler (Garbage Collector) entsorgt nicht mehr benutzte Objekte.

Tran / Hettel GDI 2 22


Klassen und Objekte

Ergänzung zu Attributen
Attribute werden fast wie lokale Variablen deklariert.
Unterschiede:
• Attribute haben Zugriffsmodifikatoren.
• Attribute dürfen an einer beliebigen Stelle außer in einer Methode deklariert
werden.
• Attribute gelten in der Klasse.
Beispiel
public class Point void f()
{ {
... ...
x = 3; // OK dagegen a = 3; // Fehler
... ...
private double x; int a;
} }

Tran / Hettel GDI 2 23


Klassen und Objekte

Instanz-Initialisierung
Attribute werden initialisiert entweder
• bei der Deklaration
Beispiel
private Button ok = new Button("OK");
...

• in einem Konstruktor
Beispiel private Button ok;
...
public Test()
{
ok = new Button("OK");
...

Tran / Hettel GDI 2 24


Klassen und Objekte

Manchmal will man die Attribute direkt vor Ort initialisieren


Instanz-Initialisierung
Syntax
{
// Initialisierungscode
}
Beispiel
private int[] table;
{ // Block für Instanzinitialisierung
table = new int[MAX_SIZE];
for (int i = 0; i < MAX_SIZE; ++i)
{
table[i] = i*i;
}
}
// .. weitere Codes

Tran / Hettel GDI 2 25


Klassen und Objekte

Mehrere Instanz-Initialisierungsblöcke sind erlaubt. Sie werden vom Compiler


zusammengefasst.
Bevor der Rumpf des Konstruktors ausgeführt wird, wird der Initialisierungsblock
ausgeführt.
Beispiel
public class Test
{
{
out.println("Testpunkt 1");
}
public Test()
{ // es steht hier super() – siehe später
out.println("Testpunkt 2");
}
}

Was wird durch new Test() ausgegeben?


Tran / Hettel GDI 2 26
Klassen und Objekte

Beachte, dass Vorort-Initialisierung auch eine Art von Instanz-Initialisierung ist


Beispiel class Test {
{
out.println("Testpunkt 1");
}
public Test() {
out.println("Testpunkt 2");
}
}

class Test2 {
Test test = new Test();
public Test2(){
out.println("Test2 Rumpf");
}
{
out.println("Hallo");
}
}

Was wird durch new Test2() ausgegeben?


Tran / Hettel GDI 2 27
Klassen und Objekte

Initialisierung von final-Attribute


final-Variablen haben
einen festen Inhalt. Sie dürfen nicht verändert werden. Häufig
werden sie bei der Deklaration initialisiert.
Beispiel
final int a = 5;
a = 6; // Fehler
final StringBuilder b = new StringBuilder();
b = new StringBuilder(); // Fehler – b darf nicht auf ein
// anderes Objekt zeigen
b.append(10); // OK – Inhalt darf verändert werden

Für final -Attribute gilt die aufgeschobene Initialisierung: final -Attribute dürfen
später im Konstruktor initialisiert werden (aber nur einmal!).
final int a;
...
a = 3; // im Konstruktor oder in der Instanzinitialisierung

Tran / Hettel GDI 2 28


Klassen und Objekte

Aufzählung (Enumeration)
Anforderung: Klasse für die Jahreszeiten.
1. Versuch: Klassenkonstanten:
public class Saison
{
public static final int FRUEHLING = 0;
public static final int SOMMER = 1;
public static final int HERBST = 2;
public static final int WINTER = 3;
}

Problem: Unsicher! Das sind nur int-Werte. Man muss bei der Verwendung immer
überprüfen, etwa
assert(saison >= FRUEHLING && saison <= WINTER);

Tran / Hettel GDI 2 29


Klassen und Objekte

2. Versuch: Klassenobjekte

public class Saison


{
public static final Saison FRUEHLING = new Saison(0);
public static final Saison SOMMER = new Saison(1);
public static final Saison HERBST = new Saison(2);
public static final Saison WINTER = new Saison(3);
private int wert;
private static String[] sText
= { "Frühling", "Sommer", "Herbst", "Winter" };
private Saison(int val) { wert = val; }
public int getVal() { return wert; }
public String toString()
{
return sStringArray[wert];
}
}

Tran / Hettel GDI 2 30


Klassen und Objekte

Probleme
− Umständlich
− Objekt kann nicht als Marke für switch-case-Anweisung verwendet werden, d.h.
es ist nicht erlaubt:
switch (saison)
{
case FRUEHLING: // code
case SOMMER: // code
case HERBST: // code
default: // code
}
Lösung (gilt ab Java 5):

enum Saison
{
FRUEHLING, SOMMER, HERBST, WINTER
}

Tran / Hettel GDI 2 31


Klassen und Objekte

Verwendung:
Saison s = Saison.FRUEHLING; // Beachte, dass der
// Qualifizierer Saison benutzt wird
switch (s)
{
case FRUEHLING: // code // Beachte: Kein Qualifizierer
case SOMMER: // code
case HERBST: // code
default: // code
}
System.out.println(s); // FRUEHLING wird ausgegeben

Es gilt:
− Saison s = new Saison(); ist
illegal.
− Der Compiler generiert die toString-Methode für die Klasse (wie der Name des
Objekts)

Tran / Hettel GDI 2 32


Klassen und Objekte

− Die Objekte sind vergleichbar (mit compareTo).


− Mit der (vom Compiler generierten) Klassenmethode values() kann man alle
enum-Objekte erhalten:
Beispiel

Saison[] saisons = Saison.values();


for (int i = 0; i < saisons.length; ++i)
{
System.out.println(saisons[i]);
}

// oder
for (Saison s: Saison.values())
{
System.out.println(s);
}

Tran / Hettel GDI 2 33


Klassen und Objekte

Erweiterung von enum

enum Saison // selbst implementierte Klasse


{
FRUEHLING("Frühling"),
SOMMER("Sommer"),
HERBST("Herbst"),
WINTER("Winter"); // Ende der Aufzählung ; notwendig
private final String name;
private Saison(String n) { name = n; }
public String getName() { return name; }
public String toString() // keine toString-Erzeugung
// vom Compiler mehr
{
return name;
}
}

Tran / Hettel GDI 2 34

Das könnte Ihnen auch gefallen