Verwenden Sie das statische Element einer Klasse für einen abgeleiteten Typ?

73

Bei der Verwendung von Resharper 4.1 bin ich auf diese interessante Warnung gestoßen: "Zugriff auf ein statisches Element eines Typs über einen abgeleiteten Typ". Hier ist ein Codebeispiel dafür, wo dies auftritt:

class A {
    public static void SomethingStatic() {
       //[do that thing you do...]
    }
}

class B : A {
}

class SampleUsage {
    public static void Usage() {
        B.SomethingStatic(); // <-- Resharper warning occurs here
    }
}

Weiß jemand, welche Probleme es gibt (falls vorhanden), wenn die statischen Elemente von A über B verwendet werden?

Schwimmen
quelle

Antworten:

84

Ein Ort, an dem es irreführend sein kann, ist, wenn es sich bei der Statik um eine Factory-Methode handelt, z. B. wenn die WebRequestKlasse über eine Factory-Methode verfügt, mit Createder dieser Codetyp geschrieben werden kann, wenn über eine abgeleitete Klasse darauf zugegriffen wird.

var request = (FtpWebRequest)HttpWebRequest.Create("ftp://ftp.example.com");

Hier requestist vom Typ, FtpWebRequestaber es ist verwirrend, weil es so aussieht, als ob es aus einer HttpWebRequest(Geschwisterklasse) erstellt wurde, obwohl die CreateMethode tatsächlich auf WebRequest(der Basisklasse) definiert ist. Der folgende Code hat eine identische Bedeutung, ist jedoch klarer:

var request = (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com");

Letztendlich gibt es kein großes Problem beim Zugriff auf eine Statik über einen abgeleiteten Typ, aber Code wird oft klarer, wenn Sie dies nicht tun.

Greg Beech
quelle
Dies ist ein Thema, an das ich noch nie gedacht habe. Danke Greg!
Schwimmen
tolle Erklärung, es war wirklich hilfreich. Erstes Ergebnis auch auf Google ^^
marcgg
1
Ja, auch Spaß , wenn jemand denkt , dass genug genug ist und nicht implementiert Createauf HttpWebRequest, die Methode zu verstecken. Neu kompilieren, Code brechen. Viele Programmiersprachen denken immer noch, dass die Welt in Position bleibt.
Maarten Bodewes
30

B.SomethingStatic()gibt die Erklärung ab, die SomethingStaticMitglied von ist B. Das ist nicht wahr. SomethingStaticist eindeutig Mitglied von A. Die Tatsache, dass es für Mitglieder von B(als wäre es ein Mitglied von B) unqualifiziert zugänglich ist, ist eine Frage der Bequemlichkeit. Die Tatsache, dass es zugänglich ist, wenn es mit einem qualifiziert Bist, ist, IMO, ein Fehler.

P Papa
quelle
Ich denke, eine Unterklasse sollte immer jede Eigenschaft einer Oberklasse erben. Speziell für das Projekt, an dem ich gerade arbeite, ist es super hilfreich bei Fabrikmustern.
NullVoxPopuli
Ich stimme dir nicht zu. Ich habe einen gültigen Fall, in dem das aktuelle Verhalten von Vorteil ist. Hier ist die Idee : class Validator : ValidatorBase<ThrowStrategy> {}. Verwendung : Validator.CheckNonEmpty(str). Vergleichen Sie dies mit ValidatorBase<ThrowStrategy>.CheckNonEmpty(str).
Gebb
@Gebb: Ich fürchte, ich verstehe deinen Standpunkt nicht. Sie haben also eine Klassenhierarchie entworfen, die schwer einzugeben ist. Wie macht das ungültig, was ich gesagt habe? Wenn ich es wäre, würde ich erwarten Validator.CheckNonEmpty, dass sich ein statisches Mitglied der ValidatorKlasse anders verhält als ValidatorBase<ThrowStrategy>.CheckNonEmptyein anderer Typ. Das tut es nicht, was verwirrend ist. Und wenn Sie eine andere abgeleitete Klasse hätten, würden Sie das auch anrufen CheckNonEmpty? Die Tatsache, dass diese Fehlfunktion Ihnen in einer bestimmten Situation das Tippen ersparen kann, macht sie nicht zu einer guten Funktion.
P Daddy
@PDaddy: Es kommt nicht auf die Eingabe an, sondern auf die Lesbarkeit. Es scheint, dass CheckNonEmptyes zur ValidatorKlasse gehört, was es nicht tut, aber das spielt keine Rolle, solange es offensichtlich ist, was es tut.
Gebb
15

Es ist normalerweise keine Warnung, nur ein Vorschlag. Sie schaffen eine unnötige Abhängigkeit von etwas.

Angenommen, Sie entscheiden später, dass B A nicht erben muss. Wenn Sie den Ratschlägen von Resharper folgen, müssen Sie diese Codezeile nicht ändern.

Daniel Earwicker
quelle
2
Sie hätten das gleiche Problem auch mit Instanzmethoden. Warum nach all dieser Logik etwas erben? oder fehlt mir etwas
NullVoxPopuli
@NullVoxPopuli - Es gibt Leute, die empfehlen, die Vererbung der Implementierung insgesamt zu vermeiden. Mehrere beliebte Java- und C # -Bücher schlagen dies vor (siehe auch dieses Dokument : isase.us/wisr3/7.pdf ). Wenn Sie jedoch eine Instanzmethode Fooin haben A, haben Sie bei einer Instanz, Bauf die durch eine Variable verwiesen wird b, nicht die gleiche Freiheit wie im statischen Fall, zu sagen, "wo" Foonachgeschlagen werden soll. Sie müssen damit beginnen b, was auch immer Sie tun. Es ist also nicht wirklich dasselbe wie bei der Statik.
Daniel Earwicker
2

Ja, ich habe das auch gesehen, ich habe immer angenommen, dass es mich nur warnt, weil es unnötig ist. A.SomethingStatic();würde das gleiche tun.

Strahl
quelle