Ich habe mehrere Klassen, die eigentlich keinen Staat brauchen. Aus organisatorischer Sicht möchte ich sie in eine Hierarchie einordnen.
Aber anscheinend kann ich keine Vererbung für statische Klassen deklarieren.
Sowas in der Art:
public static class Base
{
}
public static class Inherited : Base
{
}
wird nicht funktionieren.
Warum haben die Designer der Sprache diese Möglichkeit geschlossen?
c#
inheritance
static
Benutzer
quelle
quelle
Antworten:
Zitat von hier :
Andere Meinungen von channel9
Und als wertvolle Idee hat littleguru eine teilweise "Problemumgehung" für dieses Problem: das Singleton- Muster.
quelle
object
, und jeder muss das wissen. Statische Klassen erben also immer vonobject
, unabhängig davon , ob Sie es explizit angeben oder nicht.Der Hauptgrund, warum Sie eine statische Klasse nicht erben können, besteht darin, dass sie abstrakt und versiegelt sind (dies verhindert auch, dass eine Instanz von ihnen erstellt wird).
Also das:
kompiliert zu dieser IL:
quelle
Stellen Sie sich das so vor: Sie greifen über den Typnamen wie folgt auf statische Elemente zu:
Wenn Sie von dieser Klasse erben würden, müssten Sie über den neuen Typnamen darauf zugreifen:
Daher hat das neue Element bei Verwendung im Code keine Beziehung zum Original. Es gibt keine Möglichkeit, eine Vererbungsbeziehung für Dinge wie Polymorphismus auszunutzen.
Vielleicht denken Sie, Sie möchten nur einige der Elemente in der ursprünglichen Klasse erweitern. In diesem Fall hindert Sie nichts daran, nur ein Mitglied des Originals in einem völlig neuen Typ zu verwenden.
Vielleicht möchten Sie einem vorhandenen statischen Typ Methoden hinzufügen. Sie können dies bereits über Erweiterungsmethoden tun.
Vielleicht möchten Sie in der Lage sein, zur
Type
Laufzeit eine Statik an eine Funktion zu übergeben und eine Methode für diesen Typ aufzurufen, ohne genau zu wissen, was die Methode tut. In diesem Fall können Sie eine Schnittstelle verwenden.Am Ende gewinnt man also nichts, wenn man statische Klassen erbt.
quelle
SomeClass<T> where T:Foo
auf Mitglieder von zugreifen kannFoo
, und wennT
eine Klasse einige virtuelle statische MitgliederFoo
überschreibt, würde die generische Klasse diese Überschreibungen verwenden. Es wäre wahrscheinlich sogar möglich, eine Konvention zu definieren, über die Sprachen dies auf eine Weise tun könnten, die mit der aktuellen CLR kompatibel ist (z. B. sollte eine Klasse mit solchen Mitgliedern eine geschützte nicht statische Klasse definieren, die solche Instanzmitglieder zusammen mit einem statischen Feld enthält eine Instanz dieses Typs halten).Was Sie mithilfe der Klassenhierarchie erreichen möchten, kann lediglich durch Namespace erreicht werden. Sprachen, die Namespapiere unterstützen (wie C #), können daher keine Klassenhierarchie statischer Klassen implementieren. Da Sie keine der Klassen instanziieren können, benötigen Sie lediglich eine hierarchische Organisation der Klassendefinitionen, die Sie mithilfe von Namespaces erhalten können
quelle
Sie können stattdessen Komposition verwenden. Auf diese Weise können Sie vom statischen Typ aus auf Klassenobjekte zugreifen. Aber kann immer noch keine Schnittstellen oder abstrakten Klassen implementieren
quelle
Obwohl Sie über den Namen der geerbten Klassen auf "geerbte" statische Mitglieder zugreifen können, werden statische Mitglieder nicht wirklich geerbt. Dies ist teilweise der Grund, warum sie nicht virtuell oder abstrakt sein können und nicht überschrieben werden können. Wenn Sie in Ihrem Beispiel Base.Method () deklariert haben, ordnet der Compiler einen Aufruf von Inherited.Method () ohnehin Base.Method () zu. Sie können Base.Method () auch explizit aufrufen. Sie können einen kleinen Test schreiben und das Ergebnis mit Reflector sehen.
Also ... wenn Sie keine statischen Elemente erben können und wenn statische Klassen nur statische Elemente enthalten können , was würde das Erben einer statischen Klasse nützen?
quelle
Hmmm ... wäre es viel anders, wenn Sie nur nicht statische Klassen mit statischen Methoden hätten ...?
quelle
Eine Problemumgehung, die Sie tun können, besteht darin, keine statischen Klassen zu verwenden, sondern den Konstruktor auszublenden, sodass nur die statischen Klassenelemente außerhalb der Klasse zugänglich sind. Das Ergebnis ist im Wesentlichen eine vererbbare "statische" Klasse:
Leider können wir aufgrund der Sprachbeschränkung "by-design" Folgendes nicht tun:
quelle
Sie können etwas tun, das wie statische Vererbung aussieht.
Hier ist der Trick:
Dann können Sie dies tun:
Die
Inherited
Klasse selbst ist nicht statisch, aber wir erlauben nicht, sie zu erstellen. Es hat tatsächlich einen statischen Konstruktor geerbt, der erstelltBase
, sowie alle Eigenschaften und Methoden vonBase
sind als statisch verfügbar. Jetzt müssen Sie nur noch statische Wrapper für jede Methode und Eigenschaft erstellen, die Sie für Ihren statischen Kontext verfügbar machen müssen.Es gibt Nachteile wie die Notwendigkeit der manuellen Erstellung statischer Wrapper-Methoden und
new
Schlüsselwörter. Dieser Ansatz unterstützt jedoch etwas, das der statischen Vererbung sehr ähnlich ist.PS Wir haben dies zum Erstellen kompilierter Abfragen verwendet, und dies kann tatsächlich durch ConcurrentDictionary ersetzt werden, aber ein statisches schreibgeschütztes Feld mit seiner Thread-Sicherheit war gut genug.
quelle
Meine Antwort: schlechte Designauswahl. ;-);
Dies ist eine interessante Debatte über die Auswirkungen auf die Syntax. Der Kern des Arguments ist meiner Ansicht nach, dass eine Entwurfsentscheidung zu versiegelten statischen Klassen führte. Ein Fokus auf Transparenz der Namen der statischen Klasse, die auf der obersten Ebene angezeigt werden, anstatt sich hinter untergeordneten Namen zu verstecken ("verwirrend")? Man kann sich eine Sprachimplementierung vorstellen, die verwirrend direkt auf die Basis oder das Kind zugreifen könnte.
Ein Pseudobeispiel unter der Annahme einer statischen Vererbung wurde auf irgendeine Weise definiert.
würde führen zu:
was könnte (würde?) den gleichen Speicher wie beeinflussen
Sehr verwirrend!
Aber warte! Wie würde der Compiler damit umgehen, dass MyStaticBase und MyStaticChild in beiden dieselbe Signatur definiert haben? Wenn das Kind überschreibt, als mein obiges Beispiel NICHT den gleichen Speicher ändern würde, vielleicht? Dies führt zu noch mehr Verwirrung.
Ich glaube, es gibt eine starke Rechtfertigung für den Informationsraum für eine begrenzte statische Vererbung. Mehr zu den Grenzen in Kürze. Dieser Pseudocode zeigt den Wert:
Dann bekommen Sie:
Die Verwendung sieht aus wie:
Die Person, die das statische Kind erstellt, muss nicht über den Serialisierungsprozess nachdenken, solange sie die Einschränkungen versteht, die für die Serialisierungs-Engine der Plattform oder Umgebung gelten können.
Statik (Singletons und andere Formen von "Globals") tritt häufig beim Konfigurationsspeicher auf. Durch statische Vererbung kann diese Art der Zuweisung von Verantwortlichkeiten in der Syntax sauber dargestellt werden, um einer Hierarchie von Konfigurationen zu entsprechen. Wie ich gezeigt habe, besteht jedoch ein großes Potenzial für massive Mehrdeutigkeiten, wenn grundlegende statische Vererbungskonzepte implementiert werden.
Ich glaube, die richtige Wahl für das Design wäre, eine statische Vererbung mit bestimmten Einschränkungen zuzulassen:
Sie können denselben Speicher weiterhin über eine generische Referenz ändern
MyStaticBase<ChildPayload>.SomeBaseField
. Sie wären jedoch entmutigt, da der generische Typ angegeben werden müsste. Während die untergeordnete Referenz sauberer wäre:MyStaticChild.SomeBaseField
.Ich bin kein Compiler-Autor, daher bin ich mir nicht sicher, ob mir etwas über die Schwierigkeiten bei der Implementierung dieser Einschränkungen in einem Compiler fehlt. Trotzdem bin ich fest davon überzeugt, dass ein Informationsraumbedarf für eine begrenzte statische Vererbung besteht, und die grundlegende Antwort lautet, dass dies aufgrund einer schlechten (oder zu einfachen) Designauswahl nicht möglich ist.
quelle
Statische Klassen und Klassenmitglieder werden verwendet, um Daten und Funktionen zu erstellen, auf die zugegriffen werden kann, ohne eine Instanz der Klasse zu erstellen. Statische Klassenmitglieder können verwendet werden, um Daten und Verhalten unabhängig von der Objektidentität zu trennen: Die Daten und Funktionen ändern sich nicht, unabhängig davon, was mit dem Objekt geschieht. Statische Klassen können verwendet werden, wenn die Klasse keine Daten oder Verhaltensweisen enthält, die von der Objektidentität abhängen.
Eine Klasse kann als statisch deklariert werden, was darauf hinweist, dass sie nur statische Elemente enthält. Es ist nicht möglich, das neue Schlüsselwort zum Erstellen von Instanzen einer statischen Klasse zu verwenden. Statische Klassen werden automatisch von der Common Language Runtime (CLR) von .NET Framework geladen, wenn das Programm oder der Namespace geladen wird, der die Klasse enthält.
Verwenden Sie eine statische Klasse, um Methoden zu enthalten, die keinem bestimmten Objekt zugeordnet sind. Beispielsweise ist es häufig erforderlich, eine Reihe von Methoden zu erstellen, die nicht auf Instanzdaten reagieren und keinem bestimmten Objekt in Ihrem Code zugeordnet sind. Sie können eine statische Klasse verwenden, um diese Methoden zu speichern.
Im Folgenden sind die Hauptmerkmale einer statischen Klasse aufgeführt:
Sie enthalten nur statische Elemente.
Sie können nicht instanziiert werden.
Sie sind versiegelt.
Sie dürfen keine Instanzkonstruktoren enthalten (C # -Programmierhandbuch).
Das Erstellen einer statischen Klasse entspricht daher im Wesentlichen dem Erstellen einer Klasse, die nur statische Elemente und einen privaten Konstruktor enthält. Ein privater Konstruktor verhindert, dass die Klasse instanziiert wird.
Der Vorteil der Verwendung einer statischen Klasse besteht darin, dass der Compiler überprüfen kann, ob keine Instanzmitglieder versehentlich hinzugefügt wurden. Der Compiler garantiert, dass Instanzen dieser Klasse nicht erstellt werden können.
Statische Klassen sind versiegelt und können daher nicht vererbt werden. Sie können von keiner Klasse außer Object erben. Statische Klassen dürfen keinen Instanzkonstruktor enthalten. Sie können jedoch einen statischen Konstruktor haben. Weitere Informationen finden Sie unter Statische Konstruktoren (C # -Programmierhandbuch).
quelle
Wenn wir eine statische Klasse erstellen, die nur die statischen Elemente und einen privaten Konstruktor enthält. Der einzige Grund ist, dass der statische Konstruktor die Instanziierung der Klasse verhindert, da wir keine statische Klasse erben können. Die einzige Möglichkeit, auf das Mitglied der zuzugreifen statische Klasse unter Verwendung des Klassennamens selbst. Der Versuch, eine statische Klasse zu erben, ist keine gute Idee.
quelle