Wenn eine abstrakte Klasse eine Schnittstelle implementiert, ist es auch erforderlich, die Methoden entweder zu definieren oder zu deklarieren (wie gefragt: vor ):
%Vor%Was ist das Designprinzip der c # Sprache, um die Definition von abstrakten Methoden abstrakter Klassen zu erfordern, die Schnittstellen implementieren? Es scheint völlig redundant zu sein, dass eine abstrakte Klasse eine Methode definieren muss, die sie nicht implementiert (und sie noch schlimmer macht, denn die Klasse, die die Methode tatsächlich implementiert, muss die Methode als Überschreibung kennzeichnen). Ich sehe keinen Grund, warum eine abstrakte Klasse sich nicht wie MyInterface2 verhalten könnte, das von MyInterface erbt, aber die Methoden von MyInterface nicht deklarieren muss.
Eine abstrakte Klasse ist ein vollwertiger Typ, nur dass sie nicht instanziiert werden kann. Daher muss sein vollständiger Vertrag deklariert werden, auch wenn einige seiner Methoden nicht implementiert sind. Ein Benutzer einer bestimmten abstrakten Klasse muss in der Lage sein, an alle seine Methoden zu binden, egal ob sie von Schnittstellen kommen oder direkt in der abstrakten Klasse deklariert sind. Wenn die Methoden von Interfaces nicht (zumindest nicht) in der abstrakten Klasse deklariert wurden, konnten die verwendeten nicht an sie binden.
Außerdem sind Klassen und Schnittstellen etwas lose gekoppelt. Eine Klasse kann eine Methode deklarieren, die später einer Methode mit derselben Signatur in einer Schnittstelle zugeordnet wird, die von ihrem Nachfolger implementiert wird. Daher ist es aus Sicht des Sprachdesigns wiederum eine "gute Idee", zu verlangen, dass alle Methoden der Schnittstellen, die direkt auf einer abstrakten Klasse implementiert sind, darin tatsächlich deklariert werden.
Sie können sich eine Schnittstelle als eine lösbare Funktion vorstellen (außer wenn explizite Implementierungen verwendet werden). Die abstrakte Klasse kann eigenständig leben und ihre direkten Benutzer müssen keine ihrer Schnittstellen kennen.
Es ist eine Designeigenschaft, dass nur virtuelle Methoden ohne eine Implementierung verlassen werden können, weil der technische Mechanismus virtueller Methoden für das gesamte Konzept der Arbeit abstrakter Klassen in der Praxis genutzt werden muss.
UPDATE: Beispiel:
%Vor% Die Method
sehen die Instanz, die durch die Variable x
als Bar
angegeben ist - weder als Baz
noch als IFoo
. Mit anderen Worten, der Benutzer der Klasse Bar
kümmert sich nicht darum, ob er eine, zwei, zehn oder gar keine Schnittstelle implementiert hat. Es kann nur auf seine Mitglieder zugreifen. Es beruht auf dem Vertrag von Bar
, nicht auf IFoo
s Vertrag . Wenn also Bar
IFoo
implementiert, muss alle Mitglieder von IFoo
definieren.
Eine Methode, die Sie in einer abstrakten Klasse erstellen, die die Schnittstelle implementiert, muss nicht abstrakt sein. Abstrakte Klassen können auch nicht-abstrakte Methoden enthalten und Sie können dort eine vollständige Implementierung der Schnittstelle definieren. Die erbenden Klassen müssen diese Methoden nicht überschreiben.
Dies wird auch in MSDN für abstrakte Klassen beschrieben:
Eine abstrakte Klasse muss eine Implementierung für alle Schnittstellenelemente bereitstellen.
Eine abstrakte Klasse, die eine Schnittstelle implementiert kann die Schnittstellenmethoden auf abstrakte Methoden abbilden.
Beachten Sie das Wort "könnte", es ist nicht "muss".
Bitte beachten Sie auch, was MSDN zur Implementierung einer Schnittstelle sagt:
Wenn eine Klasse oder Struktur eine Schnittstelle implementiert, muss die Klasse oder Struktur eine Implementierung für alle von der Schnittstelle definierten Elemente bereitstellen.
Dies gilt für alle Arten von Klassen und Strukturen.
Eine Klasse, die IFoo
mit der Methode void Bar()
implementiert, hat die Option, ob sie eine öffentliche Methode Bar()
verfügbar machen will oder nicht, oder ob sie ein nicht-öffentliches Mitglied zur Implementierung der Schnittstelle verwenden möchte [C # erfordert, dass die direkte Implementierungsmethode entweder öffentlich oder privat ist; vb.net erlaubt auch protected
scope, was oft die nützlichste Sortierung für abstrakte Klassen ist.
Es gibt zwei nützliche Möglichkeiten, über die eine abstrakte Klasse IFoo.Bar()
implementieren könnte:
Beide Implementierungen sind sinnvoll. Die erste würde eine ungerechtfertigte Vermutung dafür darstellen, dass eine Klasse eine öffentliche Methode haben möchte, die nirgendwo in ihrem Code erscheint; Letzteres würde erfordern, dass der Compiler "erraten" würde, welcher Name der abstrakten Methode gegeben werden sollte. Da es kein Verhalten gibt, das eindeutig besser wäre als jede Alternative, muss der Programmierer in C # angeben, welches Verhalten gewünscht wird.