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.
public static class MyStaticBase
{
SomeType AttributeBase;
}
public static class MyStaticChild : MyStaticBase
{
SomeType AttributeChild;
}
würde führen zu:
// ...
DoSomethingTo(MyStaticBase.AttributeBase);
// ...
was könnte (würde?) den gleichen Speicher wie beeinflussen
// ...
DoSomethingTo(MyStaticChild.AttributeBase);
// ...
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:
public static class MyStaticBase<T>
{
public static T Payload;
public static void Load(StorageSpecs);
public static void Save(StorageSpecs);
public static SomeType AttributeBase
public static SomeType MethodBase(){/*...*/};
}
Dann bekommen Sie:
public static class MyStaticChild : MyStaticBase<MyChildPlayloadType>
{
public static SomeType AttributeChild;
public static SomeType SomeChildMethod(){/*...*/};
// No need to create the PlayLoad, Load(), and Save().
// You, 'should' be prevented from creating them, more on this in a sec...
}
Die Verwendung sieht aus wie:
// ...
MyStaticChild.Load(FileNamePath);
MyStaticChild.Save(FileNamePath);
doSomeThing(MyStaticChild.Payload.Attribute);
doSomething(MyStaticChild.AttributeBase);
doSomeThing(MyStaticChild.AttributeChild);
// ...
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:
- Kein Überschreiben von irgendetwas. Das untergeordnete Element kann die Basisattribute, -felder oder -methoden usw. nicht ersetzen. Das Überladen sollte in Ordnung sein, solange es einen Unterschied in der Signatur gibt, der es dem Compiler ermöglicht, untergeordnetes Element gegen Basis zu sortieren.
- Erlaube nur generische statische Basen, du kannst nicht von einer nicht generischen statischen Basis erben.
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.