Abstrakte Operationen und Klassen

Eine kleine Geschichte soll die Problematik verdeutlichen, die durch das Konstrukt der abstrakten Operationen und Klassen gelöst wird. Es war ein mal eine Klasse FormVerwalter die Kreise und Quadrate verwaltete.

FormVerwalter und Formen
FormVerwalter und Formen

Mit ausgebenInfo() wurden alle seine Formen als Liste ausgegeben und mit getGesamtflaeche():GZ ermittelte er die Fläche seiner Formen. Da hatte der König den Wunsch, dass fortan auch Dreiecke und Rechtecke verwaltet werden sollen. Soll jetzt der Formverwalter noch eine extra Liste für Dreiecke und eine für Rechtecke führen?

Generalisieren schafft Ordnung

Eine Oberklasse Form übernimmt alle gemeinsamen Eigenschaften der Formen, dieses Zusammenführen wird Generalisierung genannt. Kreis und Quadrat sind jetzt Unterklassen von Form und erben deren Eigenschaften wie groesse und alle Operationen. Es muss nur noch eine Liste dieForm[] geführt werden, diese Liste kann auch Objekte der Unterklassen aufnehmen und alle in Form vorgegebenen Operationen mit den Objekten ausführen. Wenn in einer Unterklasse eine Operation anders funktionieren soll, kann sie darin re-definiert, die geerbte Oberklassenoperation überschrieben werden. Zur Laufzeit wird die in der Klasse des jeweiligen Objekts zugehörige Operation ausgeführt: Dynamische Polymorphie

Generalisierung zu einer Klasse Form
Generalisierung zu einer Klasse Form

Die Programmiererin der Klasse Form war aber ganz unglücklich über die Operation getFlaeche():GZ, denn sie wusste nicht wie sie das programmieren soll, die Fläche einer unbekannten Form, eine 0 ausgeben ist doch auch nicht die Lösung. Und wenn die Operation in Form einfach weggelassen wird, dann kann der FormVerwalter sie bei einem Form-Objekt nicht mehr aufrufen.

public String getInfo(){
  return "Form: "+groesse;  
}
public int getFlaeche(){
  return 0; // wie soll ich das berechnen??
}

Abstract hilft

Da erinnerte sie sich an die Möglichkeit mit dem Modifizierer abstract Operationen nur deklarieren aber nicht definieren zu müssen, also keinen Code für die Ausführung schreiben zu müssen. Damit löste sie ihr Problem, allerdings wollte der Compiler noch, dass abstract in die Klassendefinition geschrieben wird. Fortan können keine Form-Objekte mehr erzeugt werden (macht ja auch keinen Sinn).

public abstract class Form{
  protected int groesse; //{>=0}
  public Form(int n){
   if(n>=0){  
      groesse = n;
    }
    else System.out.println("Negativer Wert "+n);
  }
  public abstract String getInfo();
  public abstract int getFlaeche();
}
Klassendiagramm mit abstrakter Form-Klasse
Klassendiagramm mit abstrakter Form-Klasse
  1. Eine als abstract gekennzeichnete Operation muss nicht definiert (den Programm-Code angeben) sondern nur deklariert (der Operationen-Kopf, die Schnittstelle) werden.
  2. Ist in eine Klasse eine abstrakte Operation vorhanden verlangt der Compiler die Klasse auch als abstract zu kennzeichnen. Aus “es existiert abstrakte Operation” folgt die Klasse ist abstrakt. Der Umkehrschluss stimmt nicht, es kann abstrakte Klassen ohne abstrakte Operationen geben.
  3. Von abstrakten Klassen können keine Objekte, Instanzen gebildet werden. Klar, weil es ja Operationen geben kann, für die der Programm-Code fehlt.
  4. Eine Unterklasse erbt von einer abstrakten Klasse auch alle abstrakten Operationen, wenn sie diese nicht durch konkrete Operationen überschreibt ist sie damit auch abstrakt und kann keine Objekte hervor bringen. Sollen von Unterklassen Objekte erstellt werden müssen alle Operationen konkret sein. Die abstrakte Oberklasse kann damit alle Operationen vor geben, die in konkreten Unterklassen implementiert sein müssen.

Aufgabe: Programm erweitern

Klassendiagramm der Erweiterung
Klassendiagramm der Erweiterung

Erweitern Sie das Programm entsprechend des Klassendiagramms.