Wann werden Interfaces oder abstrakte Klassen verwendet? Wann beides verwenden?

Während bestimmte Richtlinien vorschreiben, dass Sie eine Schnittstelle verwenden sollten, wenn Sie einen Vertrag für eine Klasse definieren möchten, bei der die Vererbung nicht klar ist (IDomesticated) und Vererbung, wenn die Klasse eine Erweiterung einer anderen ist (Cat : Mammal, Snake : Reptile), gibt es Fälle, in denen (meiner Meinung nach) diese Richtlinien in einen grauen Bereich eintreten.

Angenommen, meine Implementierung warCat : Pet. Pet ist eine abstrakte Klasse. Sollte das erweitert werden aufCat : Mammal, IDomesticated woherMammal ist eine abstrakte Klasse undIDomesticated ist eine Schnittstelle? Oder stehe ich im Konflikt mit derKUSS/YAGNI Prinzipien (auch wenn ich nicht sicher bin, ob es eine geben wird)Wolf Klasse in der Zukunft, die nicht in der Lage wäre, von zu erbenPet)?

Weg vom MetaphorischenCats undPetAngenommen, ich habe einige Klassen, die Quellen für eingehende Daten darstellen. Sie alle müssen irgendwie dieselbe Basis implementieren. Ich könnte einen generischen Code in einer Zusammenfassung implementierenSource Klasse und erben davon. Ich könnte auch einfach eine machenISource Benutzeroberfläche (die sich für mich "richtiger" anfühlt) und den generischen Code in jeder Klasse neu implementieren (was weniger intuitiv ist). Schließlich konnte ich "den Kuchen haben und ihn essen", indem ich sowohl die abstrakte Klasse als auch die Schnittstelle erstellte. Was ist am besten

In diesen beiden Fällen wird darauf hingewiesen, dass nur eine abstrakte Klasse, nur eine Schnittstelle und sowohl eine abstrakte Klasse als auch eine Schnittstelle verwendet werden. Sind das alles gültige Entscheidungen, oder gibt es "Regeln", nach denen eine über eine andere gestellt werden soll?

Ich möchte das klarstellen, indem ich "sowohl eine abstrakte Klasse als auch eine Schnittstelle benutze", die den Fall einschließt, in dem sie im Wesentlichen dasselbe darstellen (Source undISource beide haben die gleichen Mitglieder), aber die Klasse fügt generische Funktionen hinzu, während die Schnittstelle den Vertrag spezifiziert.

Erwähnenswert ist auch, dass diese Frage hauptsächlich für Sprachen gilt, die keine Mehrfachvererbung unterstützen (z. B. .NET und Java).

Antworten auf die Frage(7)

Ihre Antwort auf die Frage