C# Mehrfachvererbung mit Interfaces?

... komplette Frage anzeigen

4 Antworten

Hallo,

Wurde hier inzwischen ja schon ein paar mal erklärt, aber mir zumindest hat es früher geholfen, möglichst viele verschiedene Erklärungen zu hören, also hier mal mein Ansatz:

Schnittstellen dienen, so ist mir das Licht aufgegangen, der Gruppierung - wenn du dich weiter mit C#-Programmierung beschäftigst, wirst du vielleicht folgendes Szenario oder ein ähnliches erleben: Du möchtest für einen Aquarienrundgang eine Liste (oder ein Array) erstellen, worin alle möglichen Wasserfahrzeuge und Taucher zusammengefasst sind. Aber das geht ja nicht, weil man nicht einfach zwei Typen angeben kann (FALSCHER Pseudocode:

var x = new List<Wasserfahrzeug&&Taucher>();
  // Geht nicht - so eine Syntax gibt es nicht.
  // List<Wasserfahrzeug, Taucher> etc. führen auch nicht zum Ziel.

falls dir diese Syntax noch nichts sagt, entspräche das vlt.:
Wasserfahrzeug[]&&Taucher[] x;
  // was der Compiler jedoch auch nicht erkennt.

)

Daher fragt man sich nun: Warum eigentlich gerade Wasserfahrzeuge und Taucher? Antwort: Die Gemeinsamkeit dieser Typen besteht in ihrer Fähigkeit, sich unter Wasser fortzubewegen, bzw. in ihrer Wasserfestigkeit. Und diese Gemeinsamkeit definieren wir:

interface ITauchfaehig
{
   void BewegenDurchWasser(int x, int y);
     // Methode, die Parameter wären z. B. die Koordinaten
}

Nun muss diese Schnittstelle nur noch von allen Klassen, die "tauchfähig" sind, implementiert werden. Wir fügen zu ihren Signaturen hinzu:

class Wasserfahrzeug : Fahrzeug, ITauchfaehig

bzw.

class Taucher : Mensch, ITauchfaehig

Nun muss man nur noch in diesen Klassen die Versionen von BewegenDurchWasser() schreiben.

Konkret zu deiner Frage also:

Wenn du die Schnittstellen ILandfahrzeug und IWasserfahrzeug hast (anders als in meinem Beispiel oben!) sowie die diese implementierende Klasse Amphibienfahrzeug, mag das erstmal ziemlich sinnlos klingen ... aber wenn du dann noch die Klasse Automobil erstellst, die nur von ILandfahrzeug erbt, oder die Klasse UBoot : IWasserfahrzeug, zahlt sich das bereits aus: Dann kannst du nämlich einfach für die jeweilige Reise die richtigen Fahrzeuge bereitstellen, nämlich z. B. alle vom Typ IWasserfahrzeug für eine Überseereise.

Ich hoffe, ich konnte dir etwas helfen. Frag auch gern noch mal nach :)

MfG,
KnorxThieus (♂)

Antwort bewerten Vielen Dank für Deine Bewertung
Kommentar von FragerHH
24.03.2016, 06:58

Hallo,

danke für Deine interessante Antwort.

Als ich angefangen habe über Interface zu lesen stand da öfters, dass ein Interface ein "Vertrag" ist den alle Klassen einhalten müssen.

Und dass das zum Beispiel nützlich sei wenn mehrere Entwickler gemeinsam an einem Projekt arbeiten: Man einigt sich vorab über alle Methoden etc. die jede Klasse implementieren muss.

So können sich Entwickler darauf verlassen, dass ihre Kollegen bestimmte Methoden implementieren müssen - weil das Interface das eben so vorgibt.

Na ja, ich dachte mir dann dass das eher eine organisatorische Massnahme ist, denn man könnte so ein Projekt auch ohne Interfaces schaffen, eine technische Notwendigkeit für diesen Zweck Interfaces einzusetzen gibt es nicht.

Dann fand ich noch den Hinweis bzgl. Mehrfachvererbung und dass man das mit Interfaces nachbilden kann.

Und das hatte ich eine zeitlang nicht verstanden, denn ich ging davon aus, dass es bei Vererbung eben genau darum geht so viel Code wie möglich von den Klassen zu übernehmen.

Aber wie soll das gehen wenn man von Interfaces erbt?

Diese haben ja per Definition keinen Code, der vererbt werden kann.

Daher war ich etwas verwirrt...

Inzwischen ist es etwas klarer:
Es geht wohl bei der Mehrfachvererbung über Interfaces um "Gruppierungen" oder "Gemeinsamkeiten" auszunutzen wie Du es richtig genannt hast.

Ich hätte es zum Beispiel auch "Schnittmenge" genannt, aber das kommt alles auf das selbe raus:

Ziel ist es über diese Gemeinsamkeiten einen neuen Typ zu schaffen (Interfaces sind Typen, genauso wie Klassen)

Die Liste in Deinem Beispiel müsste dann wohl so aussehen, oder ?

(Pseudocode, nicht getestet)

Ich bekomme hier die spitzen Klammern nicht angezeigt daher nutze ich [] für den Typ:

list[ITauchfaehig] tauchfaehigeFahrzeuge = new list
list[ITauchfaehig]

tauchfaehigeObjekte.add(einWasserfahrzeug)
tauchfaehigeObjekte.add(einTaucher)

Das wäre dann also eine Liste, die Objekte vom Typ ITauchfaehig enthält...?

Vielleicht noch ein anderes Beispiel bzgl. "Gemeinsamkeiten" wo es nicht um eine Liste geht sondern um eine gemeinsam nutzbare Methode geht:

Nehmen wir mal 3 Klassen an:
class cHolz
class cGas
class cKohle

Auf den ersten Blick haben diese Klassen anscheinend nicht so viel gemeinsam, man würde also nicht unbedingt zwischen diesen Klassen vererben müssen (also kein subclassing nutzen).

Jedoch kann man durchaus eine Gemeinsamkeit finden, nämlich all diese Stoffe sind brennbar, wenn auch mit unterschiedlichem Heizwert.

Ich möchte nun also diese Gemeinsamkeit in meinem Programcode auszunutzen um möglichst effektiven Code zu schreiben.

Daher fasse ich diese Klassen also über ihre Gemeinsamkeit (brennbar) zusammen indem ich einen neuen Typ (IBrennbar) mittels Interface schaffe (das ist dann wohl sog. subtyping) :

interface IBrennbar
{
int Heizwert;
}

class cHolz :IBrennbar
{int Heizwert = 10}

class cGas :IBrennbar
{int Heizwert = 20}

class cKohle :IBrennbar
{int Heizwert = 30}

Dann sollte das möglich sein :

IBrennbar oHolz = new cHolz()
IBrennbar oGas = new cGas()
IBrennbar oKohle = new cKohle()

//eine einzige Methode um alle brennbaren Stoffe zu verarbeiten

verheizen (oHolz)
verheizen (oGas)
verheizen (oKohle)

void verheizen(IBrennbar irgendwasBrennbares)
{
//hier jetzt irgendwas machen...z.B je nach Heizwert erhöht sich die Zimmertemperatur irgendwie
Zimmertemperatur += irgendwasBrennbares.Heizwert
}

Neben Deinem Beispiel mit der Liste und den tauchfähigen Objekten ist das vielleicht auch noch ein Beispiel für Mehrfachvererbung... hoffe ich jedenfalls

Aber vielleicht kann man mein oder auch Dein Beispiel anderes lösen als mit Interfaces...es gibt z.B auch dynamische Objekte wie "ExpandoObject" mit denen man so was vielleicht auch machen könnte...

danke nochmal und tschüss

1

Amphibienfahrzeuge : ILandfahrzeuge, IWasserfahrzeuge

Amphibienfahrzeug muss dann alle Methoden, die in ILand- und IWasserfahrzeug deklariert sind, auch implementieren, hätte also (wenn man das so plant) zumindest alle öffentlichen Methoden der beiden anderen Fahrzeuge. 

Antwort bewerten Vielen Dank für Deine Bewertung

Der Vorteil ist:

Hat man eine Methode, die einen Parameter Fahrzeug vom Typ Amphibienfahrzeug hat, so kann man - beim Aufruf dieser Methode - für den aktuellen Parameter Fahrzeug ein Landfahrzeug oder auch ein Wasserfahrzeug einsetzen.

Antwort bewerten Vielen Dank für Deine Bewertung
Kommentar von FragerHH
22.03.2016, 13:25

Ja, OK... aber was hat das mit Mehrfachvererbung zu tun ? Wäre das nicht eher so was wie Polymorphie ?

0

Eine Klasse identifiziert sich neben ihren Daten auch durch ihr Verhalten. Das Verhalten, also die Aufgabe der Klasse, kann durch die Daten beeinflusst und verändert werden.

Eine Schnittstelle hingegen definiert nur ein Verhalten - also Was kann die Klasse, die diese Schnittstelle implementiert. Das Wie entscheidet allerdings die Klasse selbst.

In deinem Beispiel könnte die Methode "Fahren" über die Schnittstelle implementiert werden, die ihrerseits im konkreten Objekt darüber entscheidet, wie das Objekt fahren kann. Im Wasser wird es ja kaum sinnvoll sein die Radachsen anzutreiben.

Anderes Beispiel: Wenn du diverse Fahrzeuge hast, dann könnte theoretisch auch jedes dieser Fahrzeuge ein Einsatzfahrzeug mit Blaulicht und Martinshorn sein. Da würde sich eine Schnittstelle anbieten, die Methoden zum Ein- und Ausschalten des Blaulichts und des Martinshorn definiert (also was kann das Fahrzeug dadurch). Das Fahrzeug selbst (die Klasse) entscheidet dann darüber, wie das Blaulicht aussehen soll; wo es sein soll; wie hell es sein soll; mit welcher Frequenz es leuchten soll, ... und so weiter.

Antwort bewerten Vielen Dank für Deine Bewertung

Was möchtest Du wissen?