C # Design: Warum ist neu / Überschreibung auf abstrakte Methoden erforderlich, aber nicht auf virtuelle Methoden?

StackOverflow https://stackoverflow.com/questions/3634529

Frage

Warum ist neu / Override auf abstrakte Methoden erforderlich, aber nicht auf virtuelle Methoden?

Beispiel 1:

abstract class ShapesClass
{
    abstract public int Area(); // abstract!
}

class Square : ShapesClass
{
    int x, y;

    public int Area() // Error: missing 'override' or 'new'
    {
        return x * y;
    }
}

Der Compiler wird diesen Fehler zeigen: Um das aktuelle Element überschreiben, dass die Umsetzung, das Schlüsselwort override hinzuzufügen. Ansonsten das neue Schlüsselwort hinzufügen

Beispiel 2:

class ShapesClass
{
    virtual public int Area() { return 0; } // it is virtual now!
}

class Square : ShapesClass
{
    int x, y;

    public int Area() // no explicit 'override' or 'new' required
    {
        return x * y;
    }
}

Diese übersetzt werden kann, indem die Methode standardmäßig versteckt.

Ich verstehe die technischen Unterschiede. Allerdings frage ich mich, warum die Sprache auf diese Weise gestaltet. Wäre es nicht besser, die gleiche Einschränkung haben, wie auch in „Probe 2“? Ich meine, in den meisten Fällen, wenn Sie eine Methode mit dem gleichen Namen wie in der übergeordneten Klasse zu erstellen, Sie in der Regel beabsichtigt, sie außer Kraft zu setzen. Also ich ausdrücklich außer Kraft setzt Angabe denken / New wäre auch sinnvoll auf virtuelle Methoden machen.

Gibt es einen Design-weise Grund für dieses Verhalten?

Update: Die zweite Probe tatsächlich bewirkt, dass eine Warnung aus. Die erste Probe zeigt einen Fehler, da die Unterklasse benötigt wird, um die abstrakte Methode zu implementieren. Ich habe die Warnung in VS nicht .. macht mir jetzt vollkommen erfassen. Danke.

War es hilfreich?

Lösung

Unter Verwendung entweder die C # 3.0-Compiler wie in .NET 3.5 SP1 ausgeliefert, oder die C # 4.0-Compiler wie in .NET 4.0 ausgeliefert, erhalte ich die folgenden Fehler für Ihr erstes Beispiel:

  

Fehler CS0534: 'ConsoleApplication3.Square' implementiert nicht geerbt abstraktes Mitglied 'ConsoleApplication3.ShapesClass.Area ()

Und die folgende Warnung für den zweiten:

  

Warnung CS0114: 'ConsoleApplication3.Square.Area ()' versteckt geerbt Mitglied 'ConsoleApplication3.ShapesClass.Area ()'. Um das aktuelle Element überschreiben, dass Implementierung, fügen Sie das Schlüsselwort override. Ansonsten das neue Schlüsselwort hinzuzufügen.

Im ersten Fall ist es ein Fehler, weil Sie nicht tatsächlich die Basis Methode überschreiben, was bedeutet, es gibt keine Implementierung für die abstrakte Methode in einer konkreten Klasse. Im zweiten Fall ist es eine Warnung, da der Code ist technisch korrekt, aber der Compiler den Verdacht hegt, dass es nicht das, was Sie gemeint. Dies ist einer der Gründe, warum es in der Regel eine gute Idee, die „Warnungen als Fehler behandeln“ Compilation Einstellung zu aktivieren.

Also ich nicht Ihr Verhalten repro kann, und das Verhalten der Compiler sieht richtig für mich. Welche Version des Compilers verwenden Sie?

Andere Tipps

Hier ist die Antwort direkt aus dem C # spec.

  

... einen barrierefreien Namen von einem Versteck   erbte Umfang bewirkt eine Warnung sein   berichtet. Im Beispiel

class Base
{
    public void F() {}
}
class Derived: Base
{
    public void F() {}      // Warning, hiding an inherited name
}
  

die Deklaration von F in Derived Ursachen   eine Warnung gemeldet werden. Verstecken ein   erbte Name ist nicht speziell ein   Fehler, da dies ausschließen   getrennte Entwicklung von Basisklassen.   Zum Beispiel könnte die oben beschriebene Situation   zustande gekommen, weil eine spätere   Version of Base eingeführt, um eine F-Methode   Das war nicht in einem früheren   Version der Klasse. Hat das oben   Situation ein Fehler aufgetreten, dann ist jede   Wechsel zu einer Basisklasse in einem gemachten   separat versioniert Klassenbibliothek   könnte möglicherweise abgeleitet verursachen   Klassen ungültig. Die Warnung   verursacht durch eine vererbte Name kann versteckt   werden Nutzung des neuen eliminiert durch   Modifikator:

class Base
{
    public void F() {}
}
class Derived: Base
{
    new public void F() {}
}
  

Der neue Modifikator gibt an, dass der F   in Abgeleitet „neu“ ist, und dass es   in der Tat beabsichtigt, die geerbt zu verstecken   Mitglied.

Der Unterschied besteht darin, dass die abstrakte Methode sein, außer Kraft gesetzt hat, aber die virtuelle nicht.

Es ist ein Fehler die abstrakte Klasse zu erben (in einer nicht-abstrakten Klasse) ohne alle abstrakten Mitglieder der Umsetzung, aber Sie haben nur eine Warnung erhalten, wenn sie von der Klasse erben, ohne override oder new für die virtuelle Methode angeben.

ich in der ersten Art und Weise denken Sie die Compiler-Fehler, weil die abstrakte Methode verborgen ist und nicht umgesetzt (so effektiv Ihre Klasse ist falsch, und es wäre schwierig, herauszufinden, warum). Im zweiten Fall, dass Sie nur eine Warnung erhalten, weil die Klasse verwendbar ist.

Versioning

Auf den ersten Blick könnte man meinen, dass Verfahren Versteck nicht besonders nützlich erscheint. Es ist eine Situation, wo man braucht, es zu benutzen, aber. Angenommen, Sie haben eine Klasse namens MotorVehicle verwenden möchten, dass wurde von einem anderen Programmierer geschrieben, und Sie wollen diese Klasse verwenden, um Ihre eigene Klasse abzuleiten. Des Weiteren, Lassen Sie uns auch annehmen, dass Sie eine Accelerate() Methode in der abgeleiteten Klasse definieren möchten. Zum Beispiel:

public class Car : MotorVehicle
{
    // define the Accelerate() method
    public void Accelerate()
    {
        Console.WriteLine(“In Car Accelerate() method”);
        Console.WriteLine(model + “ accelerating”);
    }
}

Als nächstes nehmen wir an, dass der andere Programmierer später der Kraftfahrzeugklasse ändert und entscheidet ihre eigene virtual Accelerate() Methode hinzufügen:

public class MotorVehicle
{
    // define the Accelerate() method
    public virtual void Accelerate()
    {
        Console.WriteLine(“In MotorVehicle Accelerate() method”);
        Console.WriteLine(model + “ accelerating”);
    }
}

Die Zugabe dieses Accelerate() Verfahren durch die anderen Programmierer verursacht ein Problem: Die Accelerate() Methode in Ihrer Car Klasse versteckt die geerbte Accelerate() Methode nun definiert in ihre MotorVehicle Klasse. Später, wenn Sie Ihre Car Klasse zu kompilieren kommen, ist es nicht klar, an den Compiler ob Sie sollte eigentlich Ihre Methode die geerbte Methode zu verstecken. Aus diesem Grund, die Compiler meldet die folgende Warnung, wenn Sie versuchen, Ihre Auto-Klasse zu kompilieren:

  

Warnung CS0114: ‚Car.Accelerate ()‘ versteckt geerbt Mitglied   ‚MotorVehicle.Accelerate ()‘. Um die aktuelle Element außer Kraft gesetzt   Implementierung, fügen Sie das Schlüsselwort override. Ansonsten das neue Schlüsselwort hinzuzufügen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top