6. Klassen und Objekte


Klassendeklaration

Allerorten ist heute die Rede von "Objektorientierter Programmierung" (OOP). In diesem Teil des Kurses haben wir die Möglichkeit, uns einmal mit den Grundlagen dieser Technologie vertraut zu machen.

Die Grundlage der OOP sind die sog. Klassen. Klassen sind abstrakte Datentypen. Wir kennen alle schon Datentypen wie z.B. int und double. Diese vordefinierten Datentypen verbinden jeweils eine bestimmte Menge an Speicherplatz mit einer bestimmten Anzahl von Operationen, die man auf den Daten dieses Typs machen kann. So belegt z.B. eine Variable vom Typ int in Java gerade 4 Byte Speicherplatz und man kann sie addieren, multiplizieren, ihr einen Wert zuweisen etc. In objektorientierten Sprachen können wir nun selbst solche Datentypen entwerfen. Einen solchen Entwurf nennt man "Klasse". Wenn wir dann eine "Variable" unseres neuen Datentyps anlegen, dann erzeugen wir ein sog. "Objekt".

einfacher Datentyp-->Variable
Klasse -->Objekt

Normalerweise versucht man in der OOP, Objekte der realen Welt mit Klassen zu beschreiben und die dazugehörigen Daten in Objekten, d.h. speziellen "Variablen" zu verwalten. Dabei gilt es, für die Klassendeklaration (den "Entwurf" des neuen Datentyps) und für die Erzeugung der Objekte sprachspezifische Regeln zu beachten. Als Beispiel wollen wir gleich mal eine Klasse "Massenpunkt" deklarieren:

  class Massenpunkt {

    double q, p, m;

    Massenpunkt(double q, double p, double m) {
      this.q = q; this.p = p; this.m = m;
    }

    void euler(double kraft, double dt) {
      q += p * dt / m;
      p += kraft * dt;
    }

  }

Physikalisch ist ein Massenpunkt eine (punktförmige) Masse mit einer Ortskoordinate und einem Impuls. Nicht mehr und nicht weniger. An sinnvollen Operationen, die man mit einem Massenpunkt machen kann, steht die Neudefinition eines solchen mit sinnvollen Werten sicher an erster Stelle. Weiterhin sollte es eine Möglichkeit geben, den Massenpunkt unter dem Einfluss einer Kraft zu bewegen. Dementsprechend unsere Klassendeklaration:

Klassendeklarationen können separat in einem eigenen File oder aber innerhalb von anderen Klassendeklarationen stehen. Tatsächlich findet man, dass Java (fast) vollständig in Form von Klassen, Objekten und Methoden organisiert ist.

Anwendung von Klassen

Natürlich können wir hier nur einen ersten Eindruck der Möglichkeiten geben, welche das Klassenkonzept der Softwareentwicklung eröffnet. Betrachten wir einmal eine paint() Routine, die Gebrauch macht von allen Möglichkeiten, die uns unsere Massenpunkt - Klasse bietet:

  public void paint(Graphics g) {

    final double D = 1.0; // Federkonstante
    double tmax = 10.0;   // Simulationszeit
    double dt = 0.01;     // Zeitinterval

    setRange(0.0, tmax, -1.5, 1.5);
    g.drawLine(sx(0.0), sy(0.0), sx(tmax), sy(0.0));

    Massenpunkt M1 = new Massenpunkt(1.0, 0.0, 1.0);
    Massenpunkt M2 = new Massenpunkt(1.0, 0.0, 1.0);

    double kraft1, kraft2;

    // Schleife ueber die Zeit
    for(double t = 0.0; t < tmax; t += dt) {

      // Momentaufnahme der Kraft
      kraft1 = -D * M1.q;           // Federkraft
      kraft2 = -D * Math.sin(M2.q); // Pendel

      // Euler Integration
      M1.euler(kraft1, dt);
      M2.euler(kraft2, dt);

      // Punkte Zeichnen
      g.setColor(Color.blue);
      g.fillOval(sx(t) - 2, sy(M1.q) - 2, 4, 4);
      g.setColor(Color.red);
      g.fillOval(sx(t) - 2, sy(M2.q) - 2, 4, 4);

    }

  }

Erzeugung von Objekten

Nach Deklaration einiger Variablen wird die Skalierung unseres Bildschirmausschnittes festgelegt und eine Linie bei y = 0 eingezeichnet. Dann erfolgt die Erzeugung zweier Objekte vom Typ Massenpunkt. In den beiden Zeilen oben passieren dabei eigentlich gleich zwei Dinge gleichzeitig. Erstens wird eine Referenz auf ein Objekt vom Typ Massenpunkt erstellt:

  Massenpunkt M1;

Diese Referenz verweist nach ihrer bloßen Deklaration allerdings noch auf kein Datenobjekt, es handelt sich zunächst vielmehr um eine "Nullreferenz". Wir haben also an dieser Stelle noch keinen Speicherplatz zum Ablegen der (double) Werte für Ort, Impuls und Masse. In einem zweiten Schritt müssen wir nun Speicherplatz für diese Werte, eben gerade für ein Objekt vom Typ Massenpunkt, beim System anfordern und an M1 zuweisen:

  M1 = new Massenpunkt(1.0, 0.0, 1.0);

Dabei verwenden wir den new Operator, der dem System mitteilt, dass wir ein Objekt (oder mehrere) erzeugen möchten. Außerdem verwenden wir unseren Konstruktor, der die Attribute unseres neuen Objektes gleich mit sinnvollen Werten belegt.

Falls man in einer Klassendeklaration keinen Konstruktor definiert, wird übrigens von Java automatisch ein sog. parameterloser Konstruktor bereitgestellt.

Zugriff auf Attribute und Methoden

Attribute wie auch Methoden einer Klasse werden auch als Elemente bezeichnet. Der Zugriff auf die Elemente eines Objektes erfolgt mittels des Elementoperators, eines einfachen Punktes. So sehen wir in blau den Zugriff auf die Ortskoordinate der Massenpunkte (q) und in grün den Zugriff auf die Methode euler(). Der Vollständigkeit halber sei hier noch folgendes angemerkt:

Hier geht es weiter ...