it-swarm.com.de

Statisches C # -Mitglied "Vererbung" - warum existiert das überhaupt?

In C # werden die statischen Member einer Superklasse in den Unterklassenbereich "geerbt". Zum Beispiel:

class A { public static int M() { return 1; } }
class B : A {}
class C : A { public new static int M() { return 2; } }
[...]
A.M(); //returns 1
B.M(); //returns 1 - this is equivalent to A.M()
C.M(); //returns 2 - this is not equivalent to A.M()

Nun können Sie keine statischen Klassen erben, und der einzige Ort, an den ich mir vorstellen kann, dass statische Vererbung von Belang sein könnte, ignoriert sie völlig: Obwohl Sie eine generische Einschränkung erstellen können, die erfordert, dass der Typparameter T eine Unterklasse von A ist, können Sie ihn immer noch nicht aufrufen T.M() (was wahrscheinlich die Dinge für die VM vereinfacht), lassen Sie eine andere M-Implementierung in einer Unterklasse schreiben und verwenden Sie diese.

Die "Vererbung" statischer Member sieht also nur wie eine Namensraumverschmutzung aus. Auch wenn Sie den Namen explizit angeben (d. h. B.M), wird die Version von A noch aufgelöst.

EditMit Namespaces vergleichen:

namespace N1{  class X();   }
namespace N1.N2 {  class X();   }
namespace N1.N2.N3 { [...] }

Innerhalb von N1.N2.N3 Es macht Sinn, dass ich, wenn ich X ohne Qualifikation verwende, auf N1.N2.X verweist. Wenn ich jedoch ausdrücklich auf N1.N2.N3.X verweise - und keine solche Klasse existiert - erwarte ich nicht, dass N2s Version gefunden wird. und in der Tat meldet der Compiler einen Fehler, wenn Sie dies versuchen. Wenn ich dagegen ausdrücklich auf B.M() verweise, warum meldet der Compiler keinen Fehler? Immerhin gibt es in "B" keine "M" -Methode ...

Welchen Zweck hat dieses Erbe? Kann dieses Feature irgendwie konstruktiv genutzt werden?

43
Eamon Nerbonne

Also die "Vererbung" von statisch Mitglieder sehen nur aus wie Namespace Verschmutzung

Das ist richtig, außer dass die Verschmutzung eines Mannes ein würziger Geschmack ist.

Ich denke, Martin Fowler hat in seiner Arbeit an DSLs vorgeschlagen, die Vererbung auf diese Weise zu verwenden, um einen bequemen Zugriff auf statische Methoden zu ermöglichen, sodass diese Methoden ohne Klassennamenqualifizierung verwendet werden können. Der aufrufende Code muss sich also in einer Klasse befinden, die die Klasse erbt, in der die Methoden definiert sind. (Ich denke, es ist eine faule Idee.)

Meiner Meinung nach sollten statische Member nicht in eine Klasse mit einem nicht statischen Zweck gemischt werden. Das Problem, das Sie hier ansprechen, ist ein Teil des Grunds, warum es wichtig ist, sie nicht zu mischen.

Das Verstecken privater statischer veränderbarer Daten innerhalb der Implementierung einer ansonsten "Instanz" -Klasse ist besonders schrecklich. Aber es gibt statische Methoden, die noch schlimmer sind. Hier eine typische Verwendung von statischen Methoden, die in eine Klasse gemischt werden:

public class Thing
{
    // typical per-instance stuff
    int _member1;
    protected virtual void Foo() { ... }
    public void Bar() { ... }

    // factory method
    public static Thing Make()
    {
        return new Thing();
    }
}

Es ist das statische Fabrikmethode-Muster. Meistens ist es sinnlos, aber noch schlimmer ist, dass wir jetzt folgendes haben:

public class AnotherThing : Thing { }

Diese hat jetzt eine statische Make-Methode, die eine Thing und keine AnotherThing zurückgibt.

Diese Art von Nichtübereinstimmung impliziert stark, dass alles, was statische Methoden enthält, versiegelt werden sollte. Statische Member integrieren sich nicht gut in die Vererbung. Es macht keinen Sinn, sie erblich zu haben. Ich behalte also statische Dinge in separaten statischen Klassen und beschwert mich darüber, dass jedes Mitglied statisch deklariert werden muss, wenn ich bereits gesagt habe, dass die Klasse statisch ist.

Aber es ist nur eines dieser Dinge, die zu spät sind. Alle echten Arbeitssprachen (und Bibliotheken und Produkte) haben einige davon. C # hat bemerkenswert wenige.

24

Ich habe stattdessen Zugriff auf alle meine basischen statischen Member in abgeleiteten Klassen ..... Ansonsten müsste ich genau wissen, wo das statische Member definiert wurde, und es explizit aufrufen.

Wenn Sie Intellisense verwenden, können Sie automatisch jedes statische Element kennen, das für diese Art von Klasse verfügbar ist.

Natürlich werden sie nicht vererbt, es ist nur eine Verknüpfung

10
Luis Filipe

So funktioniert es , wäre in den meisten Fällen wahrscheinlich nur eine blöde Antwort. Aber in diesem Fall funktioniert es so; Da Sie von A ableiten, sagen Sie, dass Sie A + die zusätzlichen Funktionen sind, die Sie hinzufügen.

Daher müssen Sie auf dieselben Variablen zugreifen können wie über eine Instanz von A.

Das Erben einer statischen Klasse macht jedoch keinen Sinn, während der Zugriff auf die statischen Member/Fields/Methoden erfolgt.

Ein Beispiel dafür ist folgendes:

internal class BaseUser
{
    public static string DefaultUserPool { get; set; }
}
internal class User : BaseUser
{
    public int Id { get; set; }
    public string Name { get; set; }
    public User Parent { get; set; }
}

Wo der Test so aussieht:

User.DefaultUserPool = "Test";
BaseUser.DefaultUserPool = "Second Test";

Console.WriteLine(User.DefaultUserPool);
Console.WriteLine(BaseUser.DefaultUserPool);

Beide WriteLines geben "Second Test" aus. Dies liegt daran, dass sowohl BaseUser als auch User DefaultUserPool verwenden sollten, by design . Das Überschreiben von statisch implementierten Methoden wäre nicht sinnvoll, da es sich lediglich um einen Accessor in der Kinderklasse handelt.

Es kann nur einen geben. Eine Überschreibung würde bedeuten, dass es eine neue Implementierung für diese Unterklasse gibt, die den Begriff "statisch" aufhebt.

8
Filip Ekberg

Eigentlich ist dies, so wie ich es verstehe, nur eine vom Compiler bereitgestellte Verknüpfung. Syntaxzucker. B.M() wird nur zu A.M() kompilieren, da B keine static M() hat und A dies tut. Einfacheres Schreiben, sonst nichts. Es gibt keine "statische Vererbung".

Hinzugefügt: Und die Voraussetzung für new beim "Neudefinieren" ist so, dass Sie sich nicht versehentlich in den Fuß schießen.

5
Vilx-

Ich denke, es ist für den Zugriff auf geschützte statische Mitglieder der Basisklasse.

class Base
{
    protected static void Helper(string s)
    {
       Console.WriteLine(s);
    }
}

class Subclass : Base
{
   public void Run()
    {
       Helper("From the subclass");
    }
}
0
TrueWill

Also ... Was ist die Alternative?

Die Frage erwähnt ...

warum meldet der Compiler keinen Fehler? Immerhin gibt es in "B" keine "M" -Methode ...

Aber ist eine abgeleitete "M" Methode in der Klasse "B".

Wenn der Compiler dem Programmierer keine einheitliche virtuelle Tabelle für Basisfälle vorlegt, muss der Programmierer nach Basistypen suchen, um statische Methoden zu finden. Dies würde Polymorphismus brechen.

Wikipedia ...

Der Subtyp-Polymorphismus, der im Kontext der objektorientierten Programmierung fast allgemein als Polymorphismus bezeichnet wird, ist die Fähigkeit eines Typs A, als anderer Typ B zu erscheinen und verwendet zu werden.

In stark typisierten Sprachen bedeutet Polymorphismus normalerweise, dass Typ A irgendwie vom Typ B stammt oder Typ C eine Schnittstelle implementiert, die Typ B darstellt.

0
kervin

Ich sehe es immer als ein Mittel, um jegliche Form von Polymorphismus zu verhindern, indem die erbende Klasse die Elemente übernimmt, für die Sie die gleiche Funktion für alle untergeordneten Klassen beibehalten möchten.

ignoriere das Obige aus irgendeinem Grund, an den ich dachte, versiegelt statt statisch

Ich nehme an, Sie würden statische Elementvariablen und -funktionen verwenden, um sicherzustellen, dass Daten oder Funktionen nicht von der Klasseninstanz abhängig sind, da sie nur einmal instanziiert würden.

Ein Anwendungsbeispiel wäre beispielsweise ein Zählerwert, der einen Live-Zähler aller Instanzen der Unterklassen einer Oberklasse aufrechterhält (jede Unterklasse erhöht den statischen Zählerwert bei der Konstruktion). Dieser Zählwert wäre für alle Instanzen der Unterklasse verfügbar und gleich.

0
ChrisBD