Erstens bin ich ziemlich neu in C #. Ich möchte eine Schnittstelle haben, um eine Elementfunktion wie in dem folgenden Codeabschnitt zu deklarieren
%Vor% here Function
ist rein virtuell und sollte von Kindern von IMyInterface
implementiert werden. Ich könnte eine abstrakte Klasse anstelle einer Schnittstelle verwenden, aber dann konnte ich nicht von anderen Klassen erben ... Sagen wir zum Beispiel, dass MyAction
rekursiv ein Verzeichnis nach Dateien durchsucht und Function
auf jede gefundene Datei anwendet, um mein Beispiel zu verdeutlichen .
Wie ändere ich mein Design, um die Einschränkung zu überwinden, dass Interfaces keine Klassen implementieren können?
Edit: In C ++ würde ich Templates als solche verwenden
%Vor%Ich habe mich gefragt, ob es eine elegante Möglichkeit gibt, dies über Schnittstellen in C # zu tun.
In C # haben Sie keine Mehrfachvererbung. Sie können diese Einschränkung umgehen, indem Sie komposition verwenden.
Definieren Sie Ihre Schnittstelle so ( Function
muss hier nicht definiert werden):
Deklarieren Sie eine abstrakte Klasse mit einem abstrakten Function
und implementieren Sie diese Schnittstelle:
Aus dieser abstrakten Klasse können Sie eine konkrete Implementierung ableiten. Dies ist noch nicht Ihre "letzte" Klasse, aber es wird verwendet, um es zu komponieren.
%Vor% Kommen wir nun zu Ihrer "endgültigen", komponierten Klasse. Es wird von SomeBaseClass
abgeleitet und implementiert IMyInterface
, indem die Funktionalität von ConcreteMyInterface
:
AKTUALISIEREN
In C # können Sie lokale Klassen deklarieren. Dies kommt der Mehrfachvererbung noch näher, da Sie alles innerhalb Ihrer Kompositionsklasse ableiten können.
%Vor%Die einzige Möglichkeit, dies direkt zu handhaben, wäre die Verwendung einer abstrakten Klasse, da die Schnittstelle keine "Logik" irgendeiner Form enthalten kann und lediglich ein Vertrag ist.
Eine Alternative wäre jedoch, eine Schnittstelle und eine statische Klasse zu erstellen. Sie könnten dann Ihre Logik in eine Erweiterungsmethode über die Schnittstelle einfügen.
%Vor%Die Hauptnachteile sind hier mehr Typen, was die Wartbarkeit und die mangelnde Auffindbarkeit verringert.
Interfaces können kein Verhalten implementieren, das sie nur kontrahieren. Wenn Sie beim Definieren eines Vertrags eine Logik implementieren möchten, können Sie eine abstrakte Klasse verwenden.
Zu diesem Zweck. Sie müssen abstrakte Klasse definieren. Sie können Standardimplementierungen bereitstellen oder die Implementierung der abgeleiteten Klasse überlassen.
Wenn die abgeleitete Klasse etwas überschreiben will, kann sie das immer tun. Dies gibt ihnen die Flexibilität, Basis mit Änderungen zu verwenden, die sie überschreiben möchten.
Deklarieren Sie die Schnittstelle der Funktion (Signature und Rückgabetypen) in einer Schnittstelle, Erstellen Sie dann eine abstrakte Klasse, die zum Implementieren dieser Schnittstelle definiert ist, und implementieren Sie eine grundlegende Standardimplementierung in der abstrakten Klasse. Erstellen Sie dann weitere konkrete Klassen, die von der abstrakten Klasse erben, überschreiben Sie jedoch bei Bedarf die abstrakte Klassenbasisimplementierung mit einer anderen Implementierung.
Diese Art von Problem kann am besten überwunden werden, indem das externe Verhalten getrennt wird; MyAction
in diesem Fall von der internen Implementierung; MyFunction
.
Der Punkt hier ist zu verstehen, was Teil der Schnittstelle / Vertrag zwischen dieser Klasse und anderen sein sollte, und was sollte Teil der Umsetzung dieses Vertrages sein.
Hier ist der Vertrag zwischen diesem Objekt und seinen Konsumenten definiert;
%Vor%Nun eine Basisklasse, die diese Schnittstelle implementiert und auch ein bestimmtes Verhalten erzwingt;
%Vor%Und schließlich eine konkrete Implementierung, die sich mit den Ergebnissen von MyFunction auf eine bestimmte Art beschäftigt;
%Vor%Eine Schnittstelle ist ein Vertrag und kann keine Implementierung enthalten.
Aus Ihrer obigen Aussage:
Ich könnte eine abstrakte Klasse anstelle einer Schnittstelle verwenden, aber dann konnte ich nicht von anderen Klassen erben
Ich glaube, Sie treffen die Frage "Warum wird C # keine Mehrfachvererbung unterstützen".
Hier finden Sie einen CodeProject-Artikel zu Simulated Multiple Inheritance for C # . Sie sollten diesem Muster folgen können, um eine Umgehung des einfachen Vererbungsmodells von C # zu erreichen.