C #: Abstrakte Klassen müssen Schnittstellen implementieren?

131

Mein Testcode in C #:

namespace DSnA
{
    public abstract class Test : IComparable
    {

    }
}

Führt zu folgendem Compilerfehler:

error CS0535: 'DSnA.Test' does not implement interface member
'System.IComparable.CompareTo(object)'

Da die Klasse Testeine abstrakte Klasse ist , warum benötigt der Compiler sie, um die Schnittstelle zu implementieren? Sollte diese Anforderung nicht nur für konkrete Klassen obligatorisch sein ?

bguiz
quelle
Haha. Ich schrieb eine Sache und beschloss dann, sie zu ändern. Es tut uns leid. :)
Joel
2
Aufgrund der Abstimmungen und Kommentare zur akzeptierten Antwort glaube ich, dass die Abstimmungen aufgrund der Art und Weise erfolgen, wie die Frage formuliert ist. OP fragt "Warum ist das so?", Was außerhalb des Bereichs von Stackoverflow liegen würde. Nachdem ich selbst darauf gestoßen bin, lautet die Frage eher: "Vermisse ich etwas? Muss ich wirklich Implementierungen liefern? Besiegt das nicht den Sinn einer abstrakten Klasse?" Die Antwort lautet: "Nein, Sie müssen keine Implementierungen bereitstellen (was den Zweck einer abstrakten Klasse verletzen würde), aber hier ist, was Sie tun müssen, damit Ihre Situation funktioniert."
ToolmakerSteve
Ich habe einen Fall gefunden, in dem Sie eine Implementierung bereitstellen müssen. Hier verfügt die Schnittstelle über einen optionalen Parameter. Wenn Sie die Methode als abstrakt in die Basisklasse aufnehmen, werden die geerbten Klassen nicht ohne den optionalen Parameter kompiliert (der den Zweck eines optionalen Parameters zunichte macht). In diesem Fall werfe ich einfach NotImplementedException.
Paul McCarthy
Ignoriere meinen vorherigen Kommentar - es hat nicht wie erwartet funktioniert, das Prinzip der geringsten Überraschung gilt hier nicht.
Paul McCarthy

Antworten:

141

In C # ist eine Klasse erforderlich , die eine Schnittstelle implementiert , um alle Mitglieder dieser Schnittstelle zu definieren. Bei einer abstrakten Klasse definieren Sie diese Mitglieder einfach mit dem abstractSchlüsselwort:

interface IFoo
{
    void Bar();
}

abstract class Foo : IFoo
{
    public abstract void Bar();
}

Oder anders ausgedrückt: Sie nicht müssen „implementieren“ es (das ist eine schreckliche Beschränkung auf abstrakte Klassen wäre); In C # müssen Sie dem Compiler jedoch mitteilen, dass Sie das Geld absichtlich an konkrete Unterklassen übergeben - und die obige Codezeile zeigt, wie das geht.

Die Kommentare und Abstimmungen, die sich darüber beschweren, dass dies keine Antwort auf die Frage ist, verfehlen den Punkt. Jemand, der zu Stack Overflow kommt, diesen Compilerfehler erhalten hat, aber eine abstrakte Klasse hat, in der es ein Fehler wäre, eine Implementierung bereitzustellen, steckt ohne eine gute Lösung fest - müsste Implementierungsmethoden schreiben, die Laufzeitausnahmen auslösen, eine schreckliche Arbeit -umound - bis sie die oben genannten Informationen haben. Ob es gut oder schlecht ist, dass C # diese Aussage erfordert, liegt außerhalb des Bereichs des Stapelüberlaufs und ist weder für die Frage noch für diese Antwort relevant.

Joel
quelle
2
@ Ben Hab gerade deinen Kommentar gesehen. Sie haben es wahrscheinlich schon herausgefunden, aber falls jemand anderes es braucht. Überprüfen Sie explizite Schnittstellenimplementierungen: msdn.microsoft.com/en-us/library/ms173157.aspx
Joel
2
@Joel @Ben Ich glaube nicht, dass explizite Schnittstellen mit abstrakten Klassen funktionieren können. Im Beispielcode oben, ändern Sie die Definition in Fooan public abstract void IFoo.Bar();und Sie bekommen Beschwerden , dass „öffentlich“ und „abstrakt“ sind keine gültigen Modifikatoren.
Darren Cook
8
Dies beantwortet nicht die Frage, warum dies überhaupt notwendig ist, da dies eine abstrakte Klasse ist und der Compiler wissen sollte, wie er die Lücke ausfüllt. In Java ist dies nicht erforderlich, was mehrere nützliche Muster zulässt, z. B. Dekorationsmuster auf ioc-Containern, z. B. Spring / JavaEE (wenn Sie eine bestimmte Methode einer verwalteten Schnittstelle dekorieren müssen). Die gleiche Implementierung in.net müsste Entwickler dazu zwingen, sehr ausführlich zu sein, insbesondere auf großen Schnittstellen wie nhibernates ISession
Sheepy
1
Die Mixins von AspectJ sind ein weiteres Beispiel. Sie können Teilimplementierungen aus vielen abstrakten Klassen in einer einzigen Schnittstelle mischen. Jede abstrakte Klasse muss nur die Methode implementieren, die sie implementieren möchte. Kein dummes abstraktes Methoden-Boilerplate
stört
1
@ Sheepy - Stimmt, aber meiner Meinung nach missverstehen Sie, was der Fragesteller braucht und wie dies tatsächlich eine "Antwort" ist. Ich hatte ebenfalls die gleiche Frage - weil es keinen Sinn machte, eine Implementierung liefern zu müssen, steckte ich fest. Die Antwort lautet: Sie müssen es nicht " implementieren " - aber hier ist, was Sie tun müssen , um dem Compiler mitzuteilen, dass Sie es nicht implementieren werden. (Die Frage, auf die Sie [richtig] sagen, dass dies keine Antwort ist, wäre keine geeignete Frage zum Stapelüberlauf - sie wäre einfach als nicht zweckmäßig geschlossen worden.)
ToolmakerSteve
10

Im Gegensatz zu Java muss in C #: "Eine abstrakte Klasse Implementierungen aller Mitglieder der Schnittstellen bereitstellen, die in der Basisklassenliste der Klasse aufgeführt sind. Eine abstrakte Klasse darf jedoch Schnittstellenmethoden abstrakten Methoden zuordnen."

https://msdn.microsoft.com/en-us/library/Aa664595(v=VS.71).aspx

00jt
quelle
1
Super klare Antwort und toll, dass Sie beide Situationen
angeben
Eine Frage, die sich hier stellt, ist: Warum müssen diese C # -Kesseldeklarationen (die es offensichtlich sind) in abstrakten Klassen existieren, die ansonsten prägnant und kürzer sein könnten (was die Klassen durcheinander bringt)? In meinem C # -Projekt habe ich viele abstrakte Klassen und Schnittstellen - und was ich meistens mache, ist das Kopieren und Einfügen von Methodendeklarationen in Visual Studio.
Forsberg
5

Sie müssen die Schnittstelle nicht tatsächlich implementieren .
Die Schnittstellenmethoden / -eigenschaften können abstrakt oder auch virtuell sein. Es liegt also an den Unterklassen, sie tatsächlich zu implementieren.

Ntziolis
quelle