Helmichs Informatik-Lexikon

Abstrakte Methoden

Stark überarbeitete und erweiterte Version vom November 2022

Deklaration von abstrakten Methoden

Abstrakte Methoden sind Methoden einer Klasse, die in der Klasse zwar deklariert, aber noch nicht implementiert werden. Das folgende Beispiel zeigt eine Klasse mit einer normalen Methode und einer abstrakten Methode:

public abstract class Person
{
   String name;
    
   public Person()
   {
   }

   public void setName(String pName)
   {
      name = pName; 
   }
   
   public abstract void lasseArbeiten(int stunden);
   public abstract void zeigeDaten();
}

Quelltext 1

Während setName() eine ganz normale, nicht-abstrakte Methode ist, handelt es sich bei lasseArbeiten() und zeigeDaten() um abstrakte Methoden.

Eine abstrakte Methode besteht nur aus der Signatur (dem Kopfteil) der Methode und dem Schlüsselwort abstact. Der Rumpf der Methode (also die Implementation) fehlt und muss von der Klasse ergänzt werden, die die abstrakte Klasse (hier Person) einbindet und die abstrakte Methode (hier lasseArbeiten()) aufruft.

Eine Klasse, die mindestens eine abstrakte Methode enthält, muss ebenfalls als abstract deklariert werden.

Beim Versuch, ein Objekt einer abstrakten Klasse anzulegen, passiert unter BlueJ folgendes:

Der Versuch, ein Objekt einer abstrakten Klasse anzulegen

Die new()-Operation steht hier nicht zur Verfügung. Das heißt, von abstrakten Klassen können keine Objekte erzeugt werden.

Das führt natürlich zu der folgenden Frage: Wenn man keine Objekte von abstrakten Klassen anlegen kann, wofür ist dann das Ganze dann überhaupt gut?

Der Sinn von abstrakten Klassen bzw. Methoden

Abstrakte Methoden machen nur im Zusammenhang mit Vererbung einen Sinn. Abstrakte Klassen sind keine Baupläne für Objekte, sondern Baupläne für andere Klassen. Man kann nicht-abstrakte Tochterklassen von einer abstrakten Klasse erzeugen, und von diesen Tochterklassen kann man dann Objekte anlegen.

public class Angestellter extends Person
{
    double stundenlohn, verdienst;
    int stunden;
    
    public Angestellter(String pName, double pStundenlohn)
    {
        stundenlohn  = pStundenlohn;
        stunden = 0;
        setName(pName);
    }
    
    public void lasseArbeiten(int pStunden)
    {
       stunden   = pStunden;
       verdienst = stunden * stundenlohn;
    }
    
    public void zeigeDaten()
    {
       System.out.println("Name             : " + name);
       System.out.println("Arbeitsstunden   : " + stunden);
       System.out.println("Verdienst        : " + verdienst);
    }
}

Quelltext 2

Wenn allerdings eine Tochterklasse einer abstrakten Klasse erzeugt wird, dann müssen die abstrakten Methoden überschrieben werden. Schließlich liegt ja in der abstrakten Klasse noch keine Implementierung der abstrakten Methode vor. In der Tochterklasse muss diese Implementierung nun erfolgen.

Wenn man beispielsweise die Methode lasseArbeiten() in der Tochterklasse Angestellter auskommentiert oder ganz löscht, dann erscheint beim Kompilieren eine Fehlermeldung, die darauf hinweist, dass lasseArbeiten() eine abstrakte Methode ist und unbedingt überschrieben werden muss, also in der abgeleiteten Tochterklasse implementiert werden muss.

Betrachten wir noch folgendes Beispiel:

    public void lasseArbeiten(int irgendwas)
    {
       stunden   = irgendwas;
       verdienst = stunden * stundenlohn;
    }

Quelltext 3

Die Signatur der Methode lasseArbeiten() in der abgeleiteten Klasse Angestellter wurde hier gegenüber der Signatur in der Mutterklasse verändert. Der Parameter int Stunden wurde durch den Parameter int irgendwas ersetzt. Dieses Beispiel soll zeigen, dass die Parameterliste der abstrakten Methode nicht wortwörtlich übernommen werden muss. Aber die Anzahl, die Reihenfolge und vor allem die Datentypen der Parameter müssen übereinstimmen.

Hätte man beispielsweise

public void lasseArbeiten(double irgendwas)

als Signatur gewählt, würde der Compiler wieder einen Fehler melden, weil der Datentyp der überschriebenen Methode nicht mit dem Datentyp der abstrakten Methode übereinstimmt.

Wann setzt man abstrakte Klassen bzw. abstrakte Methoden ein?

Oft setzt man abstrakte Klassen bzw. Methoden ein, wenn geplant ist, von einer Mutterklasse mehrere Tochterklassen abzuleiten, die aber trotzdem unterschiedlich Methoden haben sollen, deren Signatur gleich ist.

Eine abstrakte Mutterklasse Fahrzeug könnte beispielsweise verschiedene Tochterklassen Flugzeug, Schiff, Lastwagen, PKW etc. ableiten, die zwar alle die Methode bewegen(double pKilometer) haben, wobei aber die Implementierung dieser Methode bei jeder Tochterklasse anders aussieht.

Trotzdem könnte nun eine andere Klasse, beispielsweise Fahrzeugpark, die bewegen()-Methode jeder Tochterklasse aufrufen, ohne sich darum kümmern zu müssen, wie die jeweilige Parameterliste aussieht. Denn alle Tochterklassen haben ja die gleiche Methoden-Signatur, weil die Methoden von der abstrakten Methode abgeleitet wurden.