Ich musste kürzlich eine abstrakte Basisklasse auf einem von mir verwendeten OSS aktualisieren, damit es durch virtuelle Erstellung besser getestet werden kann (ich konnte kein Interface verwenden, da es zwei kombiniert). Dies brachte mich zu der Überlegung, ob ich alle Methoden, die ich brauchte, als virtuell markieren sollte, oder ob ich jede öffentliche Methode / Eigenschaft als virtuell markieren sollte. Ich stimme im Allgemeinen Roy Osherove zu, dass jede Methode virtuell gemacht werden sollte, aber ich bin auf diesen Artikel gestoßen, der mich dazu brachte, darüber nachzudenken, ob dies notwendig war oder nicht . Ich werde dies der Einfachheit halber auf abstrakte Klassen beschränken (ob alle konkreten öffentlichen Methoden virtuell sein sollten, ist allerdings besonders fraglich, da ich mir sicher bin).
Ich könnte sehen, wo Sie einer Unterklasse erlauben möchten, eine Methode zu verwenden, aber nicht, dass sie die Implementierung überschreibt. Wenn Sie jedoch darauf vertrauen, dass das Substitutionsprinzip von Liskov eingehalten wird, warum sollten Sie dann nicht zulassen, dass es außer Kraft gesetzt wird? Wenn Sie es als abstrakt kennzeichnen, erzwingen Sie trotzdem eine bestimmte Überschreibung. Daher sollten meines Erachtens alle öffentlichen Methoden innerhalb einer abstrakten Klasse tatsächlich als virtuell gekennzeichnet werden.
Ich wollte jedoch fragen, ob es etwas gibt, an das ich nicht denken könnte. Sollen alle öffentlichen Methoden innerhalb einer abstrakten Klasse virtuell gemacht werden?
quelle
Antworten:
Zum Beispiel, weil ich möchte, dass die Skelettimplementierung eines Algorithmus behoben wird und nur bestimmte Teile durch Unterklassen (neu) definiert werden. Dies ist allgemein als Template-Methode bekannt (Hervorhebung von mir unten):
Aktualisieren
Einige konkrete Beispiele für Projekte, an denen ich gearbeitet habe:
In den ersten beiden Fällen verwendete die ursprüngliche Legacy-Implementierung Strategy , was zu vielen duplizierten Codes führte, die natürlich über die Jahre hin und wieder geringfügige Unterschiede aufwiesen, viele duplizierte oder leicht unterschiedliche Fehler enthielten und sehr schwer zu warten waren. Durch das Refactoring auf die Vorlagenmethode (und einige andere Verbesserungen, z. B. die Verwendung von Java-Anmerkungen) wurde die Codegröße um etwa 40-70% reduziert.
Dies sind nur die jüngsten Beispiele, die mir in den Sinn kommen. Ich könnte aus fast jedem Projekt, an dem ich bisher gearbeitet habe, weitere Fälle anführen.
quelle
Es ist durchaus sinnvoll und manchmal wünschenswert, nicht-virtuelle Methoden in einer abstrakten Basisklasse zu haben. Nur weil es sich um eine abstrakte Klasse handelt, muss nicht jeder Teil polymorph verwendbar sein.
Sie können beispielsweise die Redewendung "Nicht-virtueller Polymorphismus" verwenden, bei der eine Funktion von einer nicht-virtuellen Elementfunktion polymorph aufgerufen wird, um sicherzustellen, dass bestimmte Vor- oder Nachbedingungen erfüllt sind, bevor die virtuelle Funktion aufgerufen wird
quelle
Es reicht aus, wenn eine Klasse EINE virtuelle Methode enthält, damit die Klasse abstrakt wird. Möglicherweise möchten Sie darauf achten, welche Methoden Sie virtuell verwenden möchten und welche nicht, je nachdem, welche Art von Polymorphismus Sie verwenden möchten.
quelle
Fragen Sie sich, welche Verwendung eine nicht virtuelle Methode in einer abstrakten Klasse hat. Eine solche Methode müsste implementiert werden, damit sie nützlich ist. Aber wenn die Klasse eine Implementierung hat, kann sie trotzdem als abstrakte Klasse bezeichnet werden? Auch wenn die Sprache / der Compiler dies zulässt, macht es Sinn? Persönlich glaube ich nicht. Sie hätten eine normale Klasse mit abstrakten Methoden, die von Nachkommen implementiert werden sollen.
Meine Hauptsprache ist Delphi, nicht C #. Wenn Sie in Delphi eine Methodenzusammenfassung markieren, müssen Sie diese auch als virtuell markieren, oder der Compiler beschwert sich. Ich habe die letzten Sprachänderungen nicht zu genau verfolgt, aber wenn abstrakte Klassen in Delphi sind oder zu Delphi kommen würden, würde ich erwarten, dass sich der Compiler über nicht virtuelle Methoden, private Methoden und Methodenimplementierungen für eine als abstrakt gekennzeichnete Klasse beschwert auf Klassenebene.
quelle
abstract
markieren, müssen Sie auch die gesamte Klasse markierenabstract
.Sie machen bestimmte Methoden nicht virtuell, weil Sie nicht glauben, dass dies der Fall ist. Indem Sie bestimmte Methoden nicht virtuell machen, signalisieren Sie den Erben, welche Methode (n) implementiert werden sollen.
Persönlich mache ich häufig Methodenüberladungen, die der Einfachheit halber nicht virtuell sind, sodass Benutzer der Klasse konsistente Standardeinstellungen haben können und Implementierer nicht einmal in der Lage sind, den Fehler zu machen, dieses implizierte Verhalten zu brechen.
quelle