Helmichs Informatik-Lexikon

Vererbung

Ein sehr wichtiges und mächtiges Konzept der objektorientierten Programmierung.

Durch Vererbung kann man Tochterklassen von vorhandenen Klassen erzeugen, die sämtliche Attribute und Methoden der Mutterklasse erben.

Beispiel
public class Tier
{
   int anzahlBeine;
   int anzahlFluegel;

   public Tier(int b, int f)
   {
      anzahlBeine = b;
      anzahlFluegel = f;
    }

   public int getZahlDerBeine()
   {
      return anzahlBeine;
   }

   public int getZahlDerFluegel()
   {
      return anzahlFluegel;
   }
}

Eine normale Beispielklasse Tier mit zwei Attributen, einem Konstruktor und zwei get-Methoden.

Nun sollen weitere Klassen Saeuger, Kriechtier und Vogel angelegt werden, die im Prinzip genau so arbeiten wie die Klasse Tier. Man könnte diese Klassen nun völlig unabhängig von Tier entwickeln und würde dabei zwangsläufig den gleichen Quelltext verwenden. Sollte dann mal ein Fehler in einer der Methoden entdeckt werden, beispielsweise in getAnzahlDerBeine, so muss dieser Fehler nicht nur in der Klasse Tier beseitigt werden, sondern in allen anderen Klassen auch, die den gleichen Quelltext verwenden. Wie leicht vergisst man dann, den Fehler tatsächlich in allen Klassen zu beseitigen. Das Konzept der Vererbung vermeidet solche Fehler und vereinfacht die Entwicklung von Klassen enorm.

public class Saeuger extends Tier
{
    String fellfarbe;
    
    public Saeuger(String fell)
    {
        super(4,0);
        fellfarbe = fell;
    }
    
    public String getFellfarbe()
    {
       return fellfarbe;
    }
}

Hier sehen wie den Quelltext der Klasse Saeuger, und im Folgenden den Quelltext der Klasse Vogel:

public class Vogel extends Tier
{
    double schnabellaenge;
    String federnfarbe;
    
    public Vogel(double sl, String ff)
    {
        super(2,2);
        schnabellaenge = sl;
        federnfarbe = ff;
    }
    
    public double getSchnabellaenge()
    {
       return schnabellaenge;
    }
    
    public String getFedernfarbe()
    {
       return federnfarbe;
    }
}

Das Schlüsselwort extends kann mit "erweitert" übersetzt werden. Die Klasse Saeuger erweitert die Klasse Tier um ein zusätzliches Attribut fellfarbe und eine zusätzliche Methode getFellfarbe. Die Klasse Vogel erweitert die Klasse Tier ebenfalls, allerdings um zwei zusätzliche Attribute und zwei zusätzliche sondierende Methoden.

Darüber hinaus stehen Objekten der Klassen Saeuger und Vogel alle öffentlichen Attribute und Methoden der Klasse Tier zur Verfügung. Mit anderen Worten: Ein Vogel IST ein Tier, und ein Saeuger IST ein Tier.

Die Beziehung, die zwischen den Klassen Vogel und Tier bzw. Saeuger und Tier besteht, bezeichnet man daher auch als IST-Beziehung.

Aufruf des Konstruktors

Schauen wir uns nun den Konstruktor der Klasse Vogel an. Der Konstruktor erhält zwei Parameter vom Typ double bzw. String für die Schnabellänge und die Farbe der Federn. Die Werte dieser Parameter werden den neuen Attributen zugewiesen. Diese beiden neuen Attribute existieren nur in der Tochterklasse Vogel. Ein Objekt der Klasse Tier besitzt diese Attribute nicht. Vererbung funktioniert also immer nur in einer Richtung! Ein Vogel IST ein Tier, aber ein Tier IST NICHT ein Vogel. Im BlueJ-Fenster erkennt man diese gerichtete Beziehung an den typischen Pfeilen:

Beschreibung siehe folgenden Text

IST-Beziehungen im BlueJ-Fenster. Die Pfeilspitze zeigt stets auf die Mutterklasse.

Es reicht aber nicht aus, im Konstruktor den zusätzlichen Attributen Werte zuzuweisen. Der Konstruktor der Mutterklasse muss aufgerufen werden, dieser erwartet ja schließlich auch zwei Werte, nämlich für die Anzahl der Beine und die Zahl der Flügel. Dieser Aufruf des Mutter-Konstruktors geschieht mit dem Befehl

super(2,2);

Damit wird dem Attribut anzahlBeine der Wert 2 und dem Attribut anzahlFluegel ebenfalls der Wert 2 zugewiesen, was ja typisch für einen Vogel ist.

Zugriff auf Attribute und Methoden der Mutterklasse

Wenn ein Attribut oder eine Methode in der Mutterklasse als private deklariert wurde, so haben die Tochterklassen keinen Zugriff auf das Attribut bzw. die Methode. Deklariert man in der Mutterklasse ein Attribut oder eine Methode als public, so hat nicht nur jede Tochterklasse Zugriff darauf, sondern alle anderen Klassen ebenfalls. Das ist oft aber nicht erwünscht (Datenkapselung). Ein guter Kompromiss zwischen private und public ist daher der Zugriffsmodifizierer protected. Deklariert man in der Mutterklasse ein Attribut oder eine Methode als protected, so haben alle Tochterklassen Zugriff darauf, nicht aber andere Klassen.

Mehrfachvererbung

Neben der Einteilung der Tiere in Säugetiere, Vögel, Reptilien, Fische und so weiter könnte man alle Tiere unabhängig davon in Fleischfresser, Pflanzenfresser und Allesfresser einteilen. Es wäre doch schön, wenn man nun den Wolf, der ja zu den Säugetieren gehört, auch gleichzeitig in die Gruppe der Fleischfresser einordnen könnte, während man das Schaf, das ebenfalls zu den Säugetieren gehört, in die Gruppe der Pflanzenfresser einordnen könnte. Eine entsprechende Vererbungshierarchie sähe dann vielleicht so aus:

Beschreibung siehe folgenden Text

Durch das Einbinden von Interfaces ist eine Art Mehrfachvererbung in Java möglich

Die Klasse Wolf wäre gleichzeitig Tochterobjekt von Saeuger und von Fleischfresser, und die Klasse Schaf wäre gleichzeitig Tochterobjekt von Saeuger und Pflanzenfresser.

Eine solche Mehrfachvererbung ist in Java auf direkte Weise nicht möglich (daher kompiliert BlueJ die Klassen Wolf und Schaf auch nicht, die Darstellung bleibt schraffiert), es gibt aber Programmiersprachen, wo das der Fall ist. In Java gibt es aber eine Möglichkeit, Mehrfachvererbung zu simulieren, nämlich über die Technik der Interfaces. Darauf soll hier aber nicht weiter eingegangen werden.