Wenn wir eine Klasse erstellen, die von einer abstrakten Klasse erbt, und wenn wir die geerbte abstrakte Klasse implementieren, warum müssen wir das Schlüsselwort override verwenden?
public abstract class Person
{
public Person()
{
}
protected virtual void Greet()
{
// code
}
protected abstract void SayHello();
}
public class Employee : Person
{
protected override void SayHello() // Why is override keyword necessary here?
{
throw new NotImplementedException();
}
protected override void Greet()
{
base.Greet();
}
}
Da die Methode in ihrer übergeordneten Klasse als abstrakt deklariert ist, hat sie keine Implementierung in der übergeordneten Klasse. Warum ist hier die Schlüsselwortüberschreibung hier erforderlich?
new
Schlüsselwort" ... Sie würden auch den Fehler "Keine Methode überschreibt Basisklassenmethode" erhalten.Antworten:
"Warum?" Fragen wie diese können schwer zu beantworten sein, da sie vage sind. Ich gehe davon aus, dass Ihre Frage lautet: "Welche Argumente könnten während des Sprachdesigns vorgebracht werden, um für die Position zu argumentieren, dass das
override
Schlüsselwort erforderlich ist ?"Beginnen wir mit einem Schritt zurück. In einigen Sprachen, beispielsweise Java, sind Methoden standardmäßig virtuell und werden automatisch überschrieben. Die Designer von C # waren sich dessen bewusst und betrachteten es als kleinen Fehler in Java. C # ist nicht "Java mit den dummen herausgenommenen Teilen", wie einige gesagt haben, aber die Designer von C # wollten unbedingt aus den problematischen Designpunkten von C, C ++ und Java lernen und sie nicht in C # replizieren.
Die C # -Designer betrachteten das Überschreiben als mögliche Fehlerquelle. Schließlich ist es eine Möglichkeit, das Verhalten von vorhandenem, getestetem Code zu ändern , und das ist gefährlich. Überschreiben sollte nicht beiläufig oder versehentlich erfolgen. Es sollte von jemandem entworfen werden, der darüber nachdenkt . Aus diesem Grund sind Methoden standardmäßig nicht virtuell und Sie müssen angeben, dass Sie eine Methode überschreiben.
Das ist die grundlegende Argumentation. Wir können jetzt auf einige fortgeschrittenere Überlegungen eingehen.
Die Antwort von StriplingWarrior bietet einen guten ersten Anhaltspunkt für ein fortgeschritteneres Argument. Der Autor der abgeleiteten Klasse ist möglicherweise nicht über die Basisklasse informiert, beabsichtigt möglicherweise, eine neue Methode zu erstellen, und wir sollten nicht zulassen, dass der Benutzer versehentlich überschreibt .
Obwohl dieser Punkt vernünftig ist, gibt es eine Reihe von Gegenargumenten, wie zum Beispiel:
Lassen Sie uns dann ein noch weiter fortgeschrittenes Argument zu diesem Punkt vorbringen. Unter welchen Umständen kann der Autor einer abgeleiteten Klasse dafür entschuldigt werden, dass er nicht weiß, was die Basisklasse tut? Betrachten Sie dieses Szenario:
Wir möchten, dass der Autor von D darüber informiert wird, dass sich etwas Relevantes geändert hat . Das Relevante, was sich geändert hat, ist, dass M jetzt eine Anforderung ist und dass ihre Implementierung überlastet werden muss. DM muss möglicherweise sein Verhalten ändern, sobald wir wissen, dass es von der Basisklasse aufgerufen werden kann. Das Richtige ist, nicht still zu sagen "Oh, DM existiert und erweitert BM". Das Richtige für den Compiler ist, fehlzuschlagen und zu sagen: "Hey, Autor von D, überprüfen Sie diese Annahme, die nicht mehr gültig ist, und korrigieren Sie gegebenenfalls Ihren Code."
In Ihrem Beispiel : Angenommen , das
override
war optional auf ,SayHello
weil es eine abstrakte Methode überschreibt. Es gibt zwei Möglichkeiten: (1) Der Autor des Codes beabsichtigt, eine abstrakte Methode zu überschreiben, oder (2) die überschreibende Methode überschreibt versehentlich, weil jemand anderes die Basisklasse geändert hat und der Code jetzt auf subtile Weise falsch ist. Wir können diese Möglichkeiten nicht auseinanderhalten, wenn diesoverride
optional ist .Wenn
override
es jedoch erforderlich ist, können wir drei Szenarien unterscheiden. Wenn es einen möglichen Fehler im Codeoverride
gibt, fehlt dieser . Wenn es absichtlich überschrieben wird,override
ist es vorhanden . Und wenn es absichtlich nicht überschrieben wird, dannnew
ist es vorhanden . Das Design von C # ermöglicht es uns, diese subtilen Unterscheidungen zu treffen.Denken Sie daran , dass das Melden von Compilerfehlern das Lesen der Gedanken des Entwicklers erfordert . Der Compiler muss aus falschem Code ableiten , welchen korrekten Code der Autor wahrscheinlich im Sinn hatte , und einen Fehler angeben, der ihn in die richtige Richtung weist. Je mehr Hinweise wir den Entwickler dazu bringen können, im Code zu hinterlassen, was er gedacht hat, desto besser kann der Compiler Fehler melden und desto schneller können Sie Ihre Fehler finden und beheben.
Im Allgemeinen wurde C # jedoch für eine Welt entwickelt, in der sich der Code ändert . Viele Funktionen von C #, die "ungerade" erscheinen, sind tatsächlich vorhanden, weil sie den Entwickler informieren, wenn eine früher gültige Annahme ungültig geworden ist, weil sich eine Basisklasse geändert hat. Diese Fehlerklasse wird als "spröde Basisklassenfehler" bezeichnet, und C # bietet eine Reihe interessanter Abhilfemaßnahmen für diese Fehlerklasse.
quelle
Hiermit wird angegeben, ob Sie versuchen, eine andere Methode in der übergeordneten Klasse zu überschreiben oder eine neue Implementierung zu erstellen, die für diese Ebene der Klassenhierarchie eindeutig ist. Es ist denkbar, dass ein Programmierer die Existenz einer Methode in einer übergeordneten Klasse mit genau derselben Signatur wie die in seiner Klasse erstellte nicht kennt, was zu einigen bösen Überraschungen führen kann.
Während es stimmt, dass eine abstrakte Methode in einer nicht abstrakten untergeordneten Klasse überschrieben werden muss , hielten es die Handwerker von C # wahrscheinlich immer noch für besser, explizit zu sagen, was Sie versuchen zu tun.
quelle
Da
abstract
Methode ist eine virtuelle Methode ohne Implementierung, pro Sprache C # Spezifikation , eine Einrichtung , die abstrakte Methode implizit eine virtuelle Methode ist. Undoverride
wird verwendet, um die abstrakte oder virtuelle Implementierung zu erweitern oder zu ändern, wie Sie hier sehen könnenUm es ein wenig umzuformulieren: Sie verwenden virtuelle Methoden, um eine Art späte Bindung zu implementieren, während abstrakte Methoden die Unterklassen des Typs zwingen, die Methode explizit zu überschreiben. Das ist der Punkt, wenn die Methode ist
virtual
, kann sie überschrieben werden, wenn es eine istabstract
- es muss überschrieben werdenquelle
Um die Antwort von @ StriplingWarrior zu ergänzen, wurde meiner Meinung nach auch eine Syntax verwendet, die mit dem Überschreiben einer virtuellen Methode in der Basisklasse übereinstimmt.
C # hätte also so entworfen werden können, dass Sie das Schlüsselwort override nicht zum Überschreiben abstrakter Methoden benötigen, aber ich denke, die Designer haben entschieden, dass dies verwirrend wäre, da es nicht mit dem Überschreiben einer virtuellen Methode vereinbar wäre.
quelle
override
? Ich denke, die meisten Leute würden zustimmen, dass es absurd ist, den Autor von D zu einer unnötigen Codeänderung zu zwingen; Ihre Klasse ist in Ordnung!