Mehrfachvererbung

Vererbung mit mehr als einer Basisklasse

Bei der Objektorientierten Programmierung handelt es sich um Mehrfachvererbung, wenn eine abgeleitete Klasse direkt von mehr als einer Basisklasse erbt. Ein sequentielles, mehrstufiges Erben wird dagegen nicht als Mehrfachvererbung bezeichnet.

UML-Klassendiagramm einer Mehrfachvererbung
UML-Klassendiagramm einer Mehrfachvererbung

Ein Anwendungsbeispiel hierfür ist die Modellierung eines Amphibienfahrzeugs, das sowohl die Attribute von Landfahrzeug als auch die von Wasserfahrzeug erbt. Damit besitzt Amphibienfahrzeug sowohl eine Räderzahl als auch einen Tiefgang.

Nur wenige Programmiersprachen bieten die Möglichkeit der Mehrfach-Klassenvererbung, zum Beispiel C++, CLOS, Eiffel, ooRexx, Perl und Python. Als Einwand gegen Mehrfach-Klassenvererbung wird häufig genannt, dass sie das Design unnötig kompliziert und undurchsichtig machen kann. So kann es dadurch zu Mehrdeutigkeiten im Rahmen des Diamond-Problems kommen. Bei einigen Programmiersprachen, wie zum Beispiel Oberon und dessen Weiterentwicklungen, wurde daher bewusst auf die Möglichkeit der mehrfachen Implementationsvererbung verzichtet, was durch die Verwendung von Zwillingsklassen kompensiert werden kann.[1]

Hingegen ist Mehrfach-Schnittstellenvererbung unproblematisch. In Java, Object Pascal (Delphi), C# und VB.NET kann eine Klasse beliebig viele Schnittstellen erben. Damit verpflichtet sich diese Klasse, die Methoden der Schnittstelle zur Verfügung zu stellen, und stellt damit auch etwas Ähnliches wie die Ist-ein-Beziehung, die Verhält-sich-wie-Beziehung, her.

Mit einfacher Klassenvererbung und mehrfacher Schnittstellenvererbung sind die meisten Anforderungen an ein Software-Design realisierbar, ohne die Nachteile der uneingeschränkten Mehrfachvererbung in Kauf nehmen zu müssen.

Wegen der Probleme, die bei Mehrfachvererbung auftreten können, unterstützen einige objektorientierte Programmiersprachen keine Mehrfachvererbung. Teilweise werden Alternativkonzepte angeboten, wie zum Beispiel die Konstruktion von Zwillingsklassen. Die Programmiersprache Eiffel bietet Konstrukte zur transparenten Auflösung der bei Mehrfachvererbung auftretenden Namenskonflikte. Smalltalk und Oberon verbieten Mehrfachvererbung. Java, die .NET-Sprachen oder auch Object Pascal lassen keine Mehrfachvererbung zu, bieten jedoch einen speziellen Typ der abstrakten Klasse an, das Interface, von dem mehrfach geerbt werden kann. Im Unterschied zur Vererbung von Klassen wird hier nur die Deklaration vererbt, nicht die Implementierung der Funktionen und vor allem keine Membervariablen. Ab Java 8 kann ein Interface auch Methoden beinhalten, jedoch können diese keine Membervariablen verwenden.[2] C++ bietet das Konzept der virtuellen Basisklasse, wodurch eine Replikation der Member der Basisklasse in der abgeleiteten Klasse vermieden wird. PHP benutzt unter dem Begriff „horizontal reuse“ (Horizontale Wiederverwendung) ab der Version 5.4 sogenannte Traits, welche lose Klassenfragmente sind und in andere Klassen eingebunden werden können.[3]

Beispiel

Bearbeiten

Die folgende Implementierung zeigt ein Beispiel für Mehrfachvererbung in der Programmiersprache C++. Die Klasse SelfDrivingCar wird von den zwei Basisklassen Robot und Vehicle abgeleitet. SelfDrivingCar erbt die Methoden setProperties(...) und writeRobotMessage() von Robot und die Methoden setDimensions(...) und writeVehicleMessage() von Vehicle. Die Attribute werden nicht vererbt, weil sie mit dem Zugriffsmodifikator private deklariert sind.

#include <iostream>
using namespace std;

// Basisklasse
class Robot
{
private:
    string name;
    string manufacturer;
    string inventor;

public:
    void setProperties(string name, string manufacturer, string inventor)
    {
        this->name = name;
        this->manufacturer = manufacturer;
        this->inventor = inventor;
    }

    void writeRobotMessage()
    {
        cout << "My name is " << name << ". I was invented by " << inventor << " and manufactured by " << manufacturer << "." << endl;
    }
};

// Basisklasse
class Vehicle
{
private:
    double length, width, height;

public:
    void setDimensions(double length, double width, double height)
    {
        this->length = length;
        this->width = width;
        this->height = height;
    }

    void writeVehicleMessage()
    {
        cout << "This is a vehicle with length " << length << " meters, width " << width << " meters and height " << height << " meters." << endl;
    }
};

// Abgeleitete Klasse
class SelfDrivingCar : public Robot, public Vehicle
{
};

// Hauptmethode, die das Programm ausführt
int main()
{
    SelfDrivingCar selfDrivingCar;
    selfDrivingCar.setProperties("AIBO", "Sony Corporation", "Toshitada Doi");
    selfDrivingCar.writeRobotMessage();
    selfDrivingCar.setDimensions(4.570, 1.760, 1.470);
    selfDrivingCar.writeVehicleMessage();
}

Literatur

Bearbeiten
  • Bernhard Lahres, Gregor Rayman: Praxisbuch Objektorientierung. Von den Grundlagen zur Umsetzung. Galileo Press, Bonn 2006, ISBN 3-89842-624-6
  • Iain D. Craig: Object-Oriented Programming Languages: Interpretation. Springer Verlag, London 2007, ISBN 1-84628-773-1
Bearbeiten

Einzelnachweise

Bearbeiten
  1. Hanspeter Mössenböck: Objektorientierte Programmierung in Oberon-2. Springer-Verlag, 1993.
  2. Oracle: The Java Tutorials - Default Methods
  3. Stefan-Marr.de: PHP.next: Traits – Presentation for AFUP in Paris