Mehrfachvererbung

Manchmal wird man ziemlich unverhofft mit einem Problem konfrontiert, das man schon lange kannte, aber von dem man nicht ernsthaft erwartete, ihm jemals zu begegnen. So ging es mir mit der Mehrfachvererbung.

Ohne mich je genauer damit zu beschäftigen, war ich bisher der Meinung, es sei schon in Ordnung, dass viele Programmiersprachen Mehrfachvererbung nicht unterstützen, denn auf der einen Seite waren mir mögliche und vor allem sinnvolle Anwendungen nicht klar, aber auf der anderen Seite möglicher Ärger wie z.B. schwer verständliche Programme sehr wohl.

Umso mehr überrascht es mich, dass ich mir beim Design unseres neuen .NET-basierten Programmierwerkzeugs Triton jetzt genau diese Mehrfachvererbung wünsche, sie aber natürlich in C# nicht bekomme!

Worum geht es? Ich möchte die Funktionalität von Controls für Forms erweitern, notabene die von Standard-Controls wie TextBox, CheckBox, Button usw. Ich brauche z.B. Unterstützung für eine „schlaue“ Validierung von Eingabewerten, wo ich zwischen „validiert in Bezug auf den aktuellen Wert des Controls selbst“ und „validiert auch unter Berücksichtigung gegenseitiger Abhängigkeiten“ unterscheiden möchte.

So entsteht der Bedarf, eine neue Angabe ValidationState bei den Controls unterzubringen, am liebsten gleich zusammen mit einigen Methoden, welche das Validieren unterstützen.

Natürlich steht es mir frei, von allen schätzungsweise etwa 10 System.Windows.Forms.Control-Klassen, die ich brauche, neue Klassen abzuleiten und bei allen diesen eine Property ValidationState einzuführen, aber so erhalte ich natürlich 10 verschiedene Klassen mit 10 völlig unabhängigen und inkompatiblen Properties.

Ideal wäre natürlich, die Basisklasse Control selbst um eine Property ValidationState plus zugehörigen Code erweitern zu können, aber zumindest mit C# 3.0 wäre der einzige Weg hierzu eine Modifikation des Framework-Source-Codes und eine Neukompilation, was für mich natürlich nicht in Frage kommt. Auch eine abgeschwächte Variante, bei der ich Control unverändert lasse, aber eine eigene Klasse SmartValidationControl oder so quasi in den Baum der Vererbung „einfügen“ darf, hat dieselben nicht erfüllbaren technischen Voraussetzungen.

Und hier kommt jetzt die Mehrfachvererbung ins Spiel: 10 von diversen Controls abgeleitete Klassen wären in Ordnung, wenn sie ausser vom jeweiligen Control auch noch von einer zweiten Klasse SmartValidationControl ableiten dürften!

Was wäre mit 10 UserControl-Klassen mit einer gemeinsamen Basisklasse und mit dem jeweiligen eigentlichen Control als Kind? Dieser Ansatz ist natürlich möglich, artet aber aus in eine umfangreiche Fleissaufgabe, eine Menge Properties der Controls „durchzuschlaufen“, damit sie im Designer als Properties des Containers für Änderungen zur Verfügung stehen.

Schlussendlich bin ich beim folgendem Ansatz gelandet, den ich als das „geringste Übel“ ansehe: Ich leite 10 Klassen von 10 verschiedenen Controls ab, gebe aber allen diesen Klassen ein bestimmtes Interface, das ich dann eben 10 Mal implementieren muss.

Bei meinen Abklärungen über Mehrfachvererbung per Google bin ich über ein paar Seiten gestolpert, die sich vielleicht lohnen weiterzugeben:

Hier erläutert jemand aus dem C#-Team von Microsoft, dass die CLR selbst offenbar einen Weg bietet für Mehrfachvererbung, damit zumindest im Prinzip die Möglichkeit besteht, .NET-basierte Compiler zu bauen für Sprachen, welche Mehrfachvererbung umfassen.

hier hat jemand Mehrfachvererbung in C# so sehr vermisst, dass er sich eine „Simulation“ derselben ausgedacht hat, die recht trickreich mit Operatoren für implizite Typumwandlungen arbeitet. (Ich finde das Resultat insgesamt gesehen trotzdem ernüchternd.)

Und hier findet man schliesslich ein schon etwas älteres Interview mit dem „C# Compiler Program Manager“ bei Microsoft, dem man die offizielle Haltung von Microsoft zum Thema entnehmen kann.

Anhand der vielen Treffer, die Anfragen nach multiple inheritance oder auch spezifisch c# multiple inheritance in Google produzieren, kann man sehen, dass es sich offenbar um eine Sache handelt, die immer wieder aufkommt. Es wäre interessant zu wissen, ob es keine elegante Lösung des Problems geben kann, weil das Universum eben ist wie es ist, oder ob einfach noch niemand die geniale Idee gehabt hat…

Veröffentlicht in Keine Kategorie. Schlagwörter: , , . 4 Comments »

4 Antworten to “Mehrfachvererbung”

  1. EdelSpammer Says:

    Wäre das nicht vielleicht mit Extension Methods für Control auch gegangen?

    • René Brunner Says:

      Stimmt, die habe ich vergessen zu erwähnen – Extension Methods sind natürlich auch eine Möglichkeit, bereits bestehende Klassen trotzdem noch zu erweitern.

      In meinem konkreten Fall wären sie allerdings überfordert gewesen, weil meine Erweiterungen der Controls die Möglichkeit benötigen, neue Instanz-Variablen einzuführen.

      Natürlich könnte man diese wiederum z.B. in Hash Tables mit den Controls selbst als Schlüssel technisch völlig getrennt von den Controls führen, aber es ist fraglich, ob ein solches Vorgehen ein „kleineres Übel“ gewesen wäre als meine jetzt gewählte Implementation.

  2. EdelSpammer Says:

    nix hashtable😉 … einfach dein statusobjekt im Tag von Control einlagern.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using ExtensionMethods;
    using System.Windows.Forms;
    using ExTest;

    namespace ExTest
    {
    class Program
    {
    static void Main()
    {
    Button b = new Button();
    b.StatusNullSetzen((object)new MyStatusObject());
    Console.WriteLine(b.Test1(1));
    Console.WriteLine(b.Test1(-1));
    Console.ReadKey(false);
    }
    }
    class MyStatusObject
    {
    public int zahl = 0;
    public bool online = false;
    }

    }
    namespace ExtensionMethods
    {
    public static class MyExtensions
    {
    public static string Test1(this Control c, int i)
    {
    if (((MyStatusObject)c.Tag).zahl == i)
    return „Stimmt überein“;
    else
    return „Stimmt nicht“;
    }

    public static void StatusNullSetzen(this Control c, object statusObject)
    {
    c.Tag = statusObject;
    }
    }
    }

    p.s. Referenz auf System.Windows.Forms nicht vergessen.


Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: