Kapitel 7: Objekte und Klassen

Aus ComeniusWiki
Version vom 2. Februar 2014, 17:04 Uhr von B.Schiller (Diskussion | Beiträge)

(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche

Bisher haben wir vornehmlich Datentypen verwendet, die in JAVA vordefiniert sind (z.B.int, double, String). Die große Stärke einer objektorientierten Programmiersprache besteht darin, dass wir als Programmierer eigene Datentypen in Form von Klassen nach unseren Vorstellungen und Bedürfnissen erstellen können. Eine Klasse beschreibt entsprechend den Aufbau eines komplexen Datentyps.


Beispiele für Objekte der Klasse Rechteck:

Obj1.JPG

Wie wir bereits aus der 6.Klasse wissen, lassen sich diese Objekte der Klasse Rechteck auch formal darstellen.

Klass1.JPG

Diese Darstellung von Objekten beinhaltet neben dem Objektnamen, der nach einer Konvention immer klein geschrieben wird, die Attribute des Objekts und die jeweiligen Attributwerte. Sie definieren den Zustand des Objekts. Objekte mit den denselben Attributen sind Instanzen einer Klasse. Eine Klasse stellt einen Konstruktionsplan für bestimmte Objekte dar, der mit all seinen Informationen auch ohne diese Objekte existiert. Eine Klasse ist also keine Menge von Objekten!


Die Definition einer Klasse beinhaltet drei Bestandteile:


  • Die Datenfelder bzw. Instanzvariablen speichern die Daten, die das jeweilge Objekt benutzt.
  • Die Konstruktoren erlauben es, neue Objekte zu erzeugen und diese in einen bestimmten Anfangszustand zu versetzen.
  • Die Methoden implementieren das Verhalten der Objekte.


Exkurs: UML



Beispiel: Die Klasse Rechteck

Klass2.JPG

Instanzvariablen und Methoden haben wir bereits kennengelernt. Neu sind die sogenannten Konstruktoren.


Inhaltsverzeichnis

Konstruktor

Eine Klasse kann keinen, einen oder mehrere unterschiedliche Konstruktoren besitzen. Sie dienen dazu, ein neu gebildetes Objekt einer Klasse in einen definierten Anfangszustand zu versetzen. Welcher dies ist hängt davon ab, welcher Konstruktor bei der Objektbildung aufgerufen wird. Ein leerer (Standard-) Konstruktor muss nicht angegeben werden, er wird bei Fehlen von der JVM (Java Virtual Machine) automatisch erzeugt. Aus diesem Grund hatten wir in unseren bisherigen Aufgaben keinen expliziten Konstruktor.

Syntax:

 public nameDerKlasse(Parameter) {}


Beispiel: Konstruktoren der obigen Klasse Rechteck:

public Rechteck() weist dem Rechteck standardmäßig Werte zu.

public Rechteck(){
breite = 10;
hoehe = 7;
}

Wir erhalten bei Aufruf des Konstruktors ein Rechteck der Größe 10x7. Die restlichen Werte werden von der JVM auf einen internen Standardwert gesetzt.


public Rechteck(breite, hoehe) gibt dem User die Möglichkeit, die Größe des Rechtecks selbst zu bestimmen.


public Rechteck(int breite, int hoehe){
this.breite = breite;
this.hoehe = hoehe;
}

Hier werden nach Aufruf des Konstruktors den Instanzvariablen die entsprechenden Werte der Parameter zugewiesen. Das Schlüsselwort this liefert innerhalb eines Objekts immer eine Referenz auf das Objekt selbst, d.h. es steht in der bekannten Punktschreibweise an der Stelle des Objektnamens einfach das Wort this.


public Rechteck(breite, hoehe, fuellfarbe) gibt dem User die Möglichkeit, neben der Größe des Rechtecks auch noch dessen Füllfarbe festzulegen.


public Rechteck(int breite, int hoehe, String fuellfarbe){
this.breite = breite;
this.hoehe = hoehe;
this.fuellfarbe = fuellfarbe
}


Konstruktoren können also mit unterschiedlichen Parameterlisten deklariert sein. Man spricht hier vom Überladen des Konstruktors.


Konstruktoraufruf

Neue Instanzen einer Klasse werden mit dem Operator new erzeugt.

Rechteck rechteck1 = new Rechteck();

Rechteck rechteck2 = new Rechteck(12,8);

Rechteck rechteck3 = new Rechteck(15,4,"rot");

Die drei erzeugten Rechtecke sind vom Typ Rechteck; d.h. sie sind Instanzen der Klasse Rechteck.
rechteck1 wird mit dem Standardkonstruktor erzeugt und hat die Größe 10x7.
rechteck2 wird vom User auf die Größe 12x8 festgelegt
rechteck3 bekommt vom User die Größe 15x4 und die Füllfarbe rot zugewiesen.

Hier sollte nun deutlich werden, dass das erzeugte Objekt eine Variable ist, die nach dem Plan der Klasse Rechteck aufgebaut ist. Erst wenn das Objekt erzeugt wurde, kann mittels Punktschreibweise auch auf die Eigenschaften des Objekts zugegriffen werden. Beispiel:

rechteck1.breite = 10;

rechteck3.fuellfarbe = "rot"


Aufgaben 7.1.


Getter- und Setter-Methoden

Will man von außen auf private gesetzte Attribute zugreifen, ist dies nur indirekt möglich. Wir nutzen dazu Methoden, die das betreffende Objekt veranlassen, Werte zurückzugeben bzw. zu verändern. Zur Rückgabe von Werten nutzt man sogenannte sondierende Methoden oder Getter-Methoden. Üblicherweise verwendet man als Namen für eine derartige Methode den Bezeichner getAttributname.

Soll der Benutzer auch schreibenden Zugriff auf die Attribute haben, dann erstellt man sogenannte Setter-Methoden, die von außen einen Wert übernehmen und dem auf private gesetzten Attribut zuweisen. Als Bezeichner verwendet man analog zu den Getter-Methoden setAttributname. Beispiel:

public class Rechteck {

private int laenge;
private int breite;

public Rechteck(int laenge, int breite){
this.laenge=laenge;
this.breite=breite;
}

public getLaenge(){
   return laenge;
}

public getBreite(){
   return breite;
}

public setLaenge(int l){
   laenge=l;
}

public setBreite(int b){
   breite=b;
}
}

Setter- und Getter-Methoden müssen natürlich auf public gesetzt werden, um die ihnen zugedachte Aufgabe zu erfüllen.


Klassenvariablen und Klassenmethoden

Bis jetzt kennen wir bei Variablen zwei Typen: Lokale Variablen, wie wir sie beispielsweise in Schleifen als Zählvariablen verwenden, und Instanzvariablen. Innerhalb der Klasse Kreis, die sozusagen den Datentyp Kreis definiert, haben wir beispielsweise Radius, Fuellfarbe oder Linienstärke als Instanzvariablen. Jede Variable wird für sich separat für eine Instanz (also ein aus der Klasse erzeugtes Objekt) angelegt, d.h. jede Instanz hat eine eigene Kopie der Variablen. Die Methoden beziehen sich auf die jeweils angelegte Instanz.

Damit alle Objekte einer Klasse eine bestimmte Variable gemeinsam verwenden können, gibt es die sog. Klassenvariablen. Analog dazu benutzt man Klassenmethoden für Operationen, die sich nicht auf ein bestimmtes Objekt, sondern auf die Klasse an sich beziehen. Variablen und Methoden werden mit dem Schlüsselwort static an die jeweilige Klasse gebunden. Der Zugriff auf statische Variablen erfolgt über Klassenname.Variablenname, der Zugriff auf statische Methoden über Klassenname.Methodennname

Folgendes Beispiel soll das Konzept verdeutlichen:

In einer Klasse InstanzenZaehler wird eine statische Variable zaehler angelegt, in der die Anzahl der erzeugten Instanzen der Klasse abgespeichert wird. Über eine statische Getter-Methode kann der aktuelle Wert des Zählers abgefragt werden. In einer zweiten Klasse ZaehlerTest werden drei Instanzen der Klasse InstanzenZaehler erzeugt und als Kontrolle ihre jeweilige Rangzahl ausgegeben. Am Ende wird über die Methode getZaehler() die Anzahl der erzeugten Instanzen abgefragt.

public class InstanzenZaehler {
   
// Klassenvariable
    static int zaehler = 0;

// Instanzvariable
    int nummer;
    
// Konstruktor 
    public InstanzenZaehler() {
        zaehler= zaehler+1;
        nummer = zaehler;
    }

// Klassenmethode
    static int getZaehler() {
       return zaehler;
    }
}


public class ZaehlerTest{

public void zaehlerTest(){
    System.out.println("Klassenvariable zaehler:"+ InstanzenZaehler.getZaehler());
        
        InstanzenZaehler inst_1 = new InstanzenZaehler();
        InstanzenZaehler inst_2 = new InstanzenZaehler();
        InstanzenZaehler inst_3 = new InstanzenZaehler();
    
        System.out.println("Instanzvariable nummer im 1. Objekt: "+ inst_1.nummer);
        System.out.println("Instanzvariable nummer im 2. Objekt: "+ inst_2.nummer);
        System.out.println("Instanzvariable nummer im 3. Objekt: "+ inst_3.nummer);

        System.out.println("Klassenvariable zaehler: " + InstanzenZaehler.getZaehler());
   
}
}


Aufgaben 7.3.