Zur Hauptnavigation springen [Alt]+[0] Zum Seiteninhalt springen [Alt]+[1]

Objekte und Klassen

Programmiersprachen unabhängig soll nun möglichst genau beschreiben werden, was unter einem Objekt zu verstehen ist. Dabei soll (soweit möglich und sinnvoll) eine Objekt-Analogie aus der realen Welt betrachtet werden. Sie soll uns helfen, die abstrakten Begriffe anschaulicher zu machen.

Zunächst ist ein Objekt ein Bestandteil des Programms. Es besteht aus Attributen und Methoden. In den Attributen ist der Zustand des Objekts festgehalten, durch die Methoden wird das Verhalten des Objekts bestimmt. In der Regel sind die Attribute von außen nicht erkennbar. Dadurch sind diese Zustands-Daten geschützt.

Allerdings erlaubt das Objekt, eine „Anfrage“ zu stellen. Diese Anfrage ist nichts anderes, als dass von außen eine Methode des Objekts „aufgerufen“ wird.

Schematisch:

Schema

Durch diese Anfrage wird die Methode aktiv und liefert dem Anfragenden, ohne nach außen zu zeigen, was im Inneren des Objekts vorgeht, entweder als „Antwort“ die gewünschten Daten oder die gewünschte Aktion wird (eventuell ohne Daten-Rückgabe) ausgeführt.

Um die neuen Begriffe etwas klarer zu machen, werden wir nun versuchen, ein reales Objekt „(Röhren bzw. CRT-)Fernsehapparat“ zu modellieren.

Zunächst hat der konkrete CRT-Fernseher, 32 Zoll, (das Objekt der Klasse CRT- Fernseher) feststehende (Daten-)Attribute. Zum Beispiel die Größe der Bildschirmdiagonalen, die Gerätetiefe, die Farbe etc. Dies sind gewiss Daten, die sich durch eine Anfrage nicht ändern lassen, auch wenn das mancher gerne hätte....

Es gibt aber weitere Attribute: Eingestellter Kanal, Lautstärke, Helligkeit des Bildes….

Häufig kann man hier einen bestimmten Wert, sagen wir zwischen 0 und 100 wählen. Damit das klappt, muss das Objekt Methoden haben, wie Kanal wechseln, Lautstärke oder Helligkeit verändern und so weiter.

Was genau an Änderungen der (physikalischen) Daten innen vorgenommen wird, weiß der Anfragende nicht. Er muss es auch nicht wissen. Attribute, wie „benötigte Leistung“ sind private und daher gekapselt. Das bedeutet, dass man von außen diese Werte nicht „sehen“ und direkt beeinflussen kann. Die Zahl für die eingestellte Lautstärke (z.B. 45) ist private und nur nach außen sichtbar, wenn es eine zugehörige get-Methode gibt.

Wenn eine Elektronik-Firma einen besonders großen LCD-Fernsehapparat bauen will, muss sie das Gerät dabei nicht neu erfinden! Auch bei dem besonders großen Gerät sind doch viele Methoden und Attribute gleich oder ähnlich wie bei den kleineren Geräten. Daher tut man gut daran, wenn man zunächst möglichst allgemein eine Beschreibung (Bauplan) für das Gerät Fernseher festschreibt. In OOP heißt eine solche allgemeine Beschreibung eine Klasse.

Ein Fernsehapparat besteht im Wesentlichen aus einem Gehäuse (mit Netzteil, Empfangsteil, Ein-und Ausgängen und Bedienelementen), der Bildröhre und aus dem Audio-Teil. Eine Fernbedienung liegt meist ebenfalls bei. Der Einfachheit halber werden zur Veranschaulichung von Klassen zunächst nur die Bildschirme betrachtet. Es gibt zum Beispiel CRT-(das sind die alten Bildröhren), LCD-, Plasma- und Ambilight-Bildschirme (Hintergrund-Licht-Bildschirme). All diese Bildschirme haben Gemeinsamkeiten, wie die Tatsache, dass es eine Bildschirm­diagonale (meist in Zoll) gibt. Außerdem kann man bei allen die Helligkeit und den Kontrast regeln. Eine abstrakte Bildröhre, die alle Gemeinsamkeiten aus sich bündelt, gibt es in Wirklichkeit natürlich nicht. Eine abstrakte Klasse Bildschirm sehr wohl.

Mit Hilfe der UML kann man sie grafisch darstellen. Wir verwenden hierzu, wie auch zum programmieren, den JavaEditor von Gerhard Röhner. Und so sieht eine Klasse im UML-Diagramm aus:

Klasse im UML-Diagramm

Damit die Übersichtlichkeit nicht leidet, werden hier nur wenige typische Attribute verwendet.

Der Java-Editor erzeugt den passenden Code-Rumpf selbständig. Hier wurden nur im Konstruktor die Anfangswerte von kontrast und helligkeit von Hand ergänzt:


  public Bildschirm(int diagonale) {
      this.diagonale = diagonale;
      this.helligkeit = 10;
      this.kontrast = 10;
  }

Nach Definition nennt man eine Klasse abstrakt, wenn mindestens eine ihrer Methoden nicht explizit angeben ist. Solche Methoden, bei denen nur der Methodenrumpf angelegt ist, nennt man abstrakte Methoden (im Bild oben kursiv dargestellt: getTyp():String). Mit der Klasse Bildschirm will man ja nur festhalten, was alle Bildschirme gemeinsam haben, ohne dabei an ein konkretes Gerät zu denken.

Man kann es auch so ausdrücken: Die Klasse Bildschirm ist in diesem Sinn eine abstrakte Klasse, weil sich in den „Bauplänen“ für Bildschirm lediglich der Name für die Methode getTyp() vermerkt ist. Alles andere wäre ja auch Unsinn, denn erst in den abgeleiteten Klassen, wie CrtBildschirm, LcdBildschirm etc. kann eine konkreter Anweisung für diese Methode formuliert werden, denn dieser ruft ja immer den jeweiligen Typ auf.

Weil es den abstrakten Bildschirm nicht gibt, kann man sinnvollerweise auch kein Objekte aus dieser Klasse erzeugen. Ein Objekt wäre ja der Repräsentant für einen realen Bildschirm. Aber man kann natürlich jetzt abstrakte Bildschirme, wie den Plasma-Bildschirm aus der Bildschirm-Klasse ableiten.

abgeleitete Klassen der Bildschirm-Klasse

Die Basis-Klasse Bildschirm hat mehrere abgeleitete Klassen: AmbilightBildschirm, CrtBildschirm, LcdBildschirm und PlasmaBildschirm (letzterer ist im nächsten Bild nicht dargestellt).

Aus diesen lassen sich weitere Klassen ableiten. Zum Beispiel aus CrtBildschirm CrtBildschirm50Hz und CrtBildschirm100Hz. Und immer erben die abgeleiteten Klassen die Attribute und Methoden der Basis-Klassen, d.h. ein Objekt aus der abgeleiteten Klasse enthält somit immer auch Attribute und Methoden der Basisklasse.

abgeleitete Klassen

Im obigen Bild sind per Rechtsklick auf die Klasse AmbilightBildschirm und LcdBildschirm (Kontextmenü) einzelne Objekte erzeugt („instanziiert“) worden. Die Objekte haben die Namen ambilightBildschirm1 und lcdBildschirm1. Per Rechtsklick auf ein Objekt, kann man nun die vorhandenen Methoden testen. So ließe sich beispielsweise durch die Wahl von void setHelligkeit(int Helligkeit) der Wert für die Helligkeit einstellen. („void“ bedeutet nur, dass kein Rückgabewert erwartet wird). So wie bei einem echten Bildschirm auch bereits Vorrichtungen für die Helligkeitseinstellung implementiert sind.

Das kann man direkt im UML-Diagramm testen, denn danach sollte der Wert der Helligkeit im entsprechenden Objekt den Wert annehmen, den man eingestellt hat.

Wird, wie im Bild oben per Rechtsklick ein Objekt lcdBildschirm1 erzeugt, so bedeutet dies zunächst, dass im „Heap“ (= bestimmter Bereich des RAM) nach Vorgabe der Klassendefinition durch den Konstruktor konkrete Werte in die vorher undefinierten Speicherinhalte geschrieben werden. Die Klassendefinition kann man sich wie einen Stempel vorstellen, der bei jedem neu zu bildenden Objekt einen neuen Abdruck im Heap hinterlässt. Dieser Abdruck beinhaltet den Speicherbedarf. Jedes Objekt hat auf diese Weise seinen „eigenen“ Speicherinhalt. In den Speicher werden dann zum Beispiel die Attribute eingetragen. Erst dadurch können konkrete Berechnungen mit dem Objekt durchgeführt werden.

Klassen beschreiben also die gemeinsamen Attribute und Methoden einer Menge von gleichartigen Objekten. Durch die Klassendefinition werden „Vorlagen“ (Stempel) für die nötigen Speicherreservierungen der zu erzeugenden Objekte erstellt.

Objekte sind die konkreten erzeugten Exemplare einer Klasse. In unserem Beispiel ist also der reale, mit Händen zu greifende CRT-Fernseher, 32 Zoll ein Objekt der Klasse CRT-Fernseher. Es kann viele verschiedene Objekte einer Klasse geben.

Objekte benötigen also Platz im Speicher. Diesen Platz besorgt der Konstruktor der Klasse. Wird das Objekt nicht mehr benötigt, sorgt der Destruktor dafür, dass der Platz wieder freigegeben wird. Verwendet man als Programmiersprache Java, so hat man mit den beiden nicht viel zu tun. Der Garbage Collector sorgt von Zeit zu Zeit automatisch dafür, dass nicht mehr benötigte Exemplare gelöscht werden. Ruft man in Java keinen eigenen Konstruktor auf, so wird bei der Bildung eines Exemplars automatisch ein Standard-Konstruktor benutzt. Will man allerdings bei der Erzeugung des Objekts einige Eigenschaften initialisieren, so überschreibt man den Standard-Konstruktor (siehe nächster Abschnitt).

Java-Editor

Es ist durchaus von Vorteil, wenn man die Klassen mit ihren Attributen und Methoden im UML-Tool des Java-Editors erzeugt. Ein Beispiel: In dem Moment, in dem man die Klasse AmbilightBild­schirm erzeugt, legt man im Programm­ordner eine Java-Datei gleichen Namens an:

AmbilightBildschirm.java

Im Klassen-Editor kann man dann alle gewünschten Attribute und Methoden gestalten. Auch die Methode Konstruktor wird hier den eigenen Wünschen angepasst (siehe Bild unten). Auch hier wird der Code-Rumpf automatisch erzeugt. Von Hand werden danach nur noch die Ergänzungen geschrieben, die der Editor nicht erraten kann.

Java-Editor von Gerhard Röhner (javaeditor.org)

Java-Editor von Gerhard Röhner (javaeditor.org)

Handelt es sich bei der neu erzeugten Klasse um eine abgeleitete Klasse, so trägt man dies unter dem Tab „Klasse“ ein. Hier kann auch eingestellt werden, ob die Klasse abstrakt sein soll oder nicht.

UML-Klassen-Editor

Im folgenden Code-Listing für die Klasse AmbilightBildschirm sind die von Hand eingetragenen Teile durch Fettschrift hervorgehoben. Die automatischen Kommentare sind in blauer Schrift:


  public class AmbilightBildschirm extends Bildschirm {

    // Anfang Attribute
    protected int umgebungslicht;
    // Ende Attribute

    public AmbilightBildschirm(int diagonale) {
      super(diagonale);
      this.umgebungslicht = 20;
      this.kontrast = 20;
      this.helligkeit = 18;
    }

    // Anfang Methoden

    public void setHelligkeit(int helligkeit) {
      super.setHelligkeit(helligkeit);
      this.umgebungslicht = this.helligkeit / 4 + this.kontrast /2;
    }

    public void setKontrast(int kontrast) {
      super.setKontrast(kontrast);
      this.umgebungslicht = this.helligkeit / 4 + this.kontrast /2;
    }

    public String getTyp() {
      return "AMBILIGHT";
    }

    // Ende Methoden
  } // end of AmbilightBildschirm

Analog zu den Bildschirm-Klassen werden nun die Audio-Klassen aufgebaut. Die Klasse Audio ist (wie die Klasse Bildschirm) abstrakt. Für die technisch weniger Interessierten muss erwähnt werden, dass es im Bereich der Audio-Verarbeitung analoge und digitale Geräte gibt. Als Ausgabeformate kommen Stereo, DolbyDigital, Digital 5.1 und Digital 7.1 in Frage (nur die beiden ersten sind im Bild unten dargestellt).

Aufbau Audio-Klasse

Und jetzt wird zusammengebaut! Das Gehäuse mit all seinen Gerätschaften fehlt noch. Die zugehörige Klasse soll schlicht Fernseher heißen. Sie bekommt unter anderem das Attribut kanal und die Methode naechsterKanal. Neu sind dabei die Verbindungen zwischen dem Fernseher und dem Bildschirm bzw. dem Audio-Teil. Klar, ein Fernseher hat eine Bildröhre und er hat ein Audio-System. Mit diesen (und anderen) Verbindungen beschäftigt sich der folgende Abschnitt. Hier schon einmal eine Übersicht:

Übersicht Klassen

Im diesem Bild des UML-Klassendiagramms sind Vererbung und Aggregation, die im nächsten Kapitel behandelt werden, schon vorhanden.

 

 

Einführung: Herunterladen [odt][330 KB]

 

Weiter zu Beziehungen