La mia risposta: scarsa scelta progettuale. ;-)
Questo è un dibattito interessante incentrato sull'impatto della sintassi. Il cuore dell'argomento, a mio avviso, è che una decisione di progettazione ha portato a classi statiche sigillate. Un focus sulla trasparenza dei nomi della classe statica che appare al livello più alto invece di nascondersi ("confondere") dietro i nomi dei figli? Si può immaginare un'implementazione del linguaggio che potrebbe accedere direttamente alla base o al bambino, confondendo.
Un pseudo esempio, supponendo che l'ereditarietà statica sia stata definita in qualche modo.
public static class MyStaticBase
{
SomeType AttributeBase;
}
public static class MyStaticChild : MyStaticBase
{
SomeType AttributeChild;
}
porterebbe a:
// ...
DoSomethingTo(MyStaticBase.AttributeBase);
// ...
quale potrebbe (avrebbe?) influire sulla stessa memoria di
// ...
DoSomethingTo(MyStaticChild.AttributeBase);
// ...
Molto confuso!
Ma aspetta! In che modo il compilatore gestirà MyStaticBase e MyStaticChild con la stessa firma definita in entrambi? Se il bambino ha la precedenza sul mio esempio di cui sopra NON cambierebbe la stessa memoria, forse? Questo porta ad ancora più confusione.
Credo che ci sia una forte giustificazione dello spazio informativo per l'ereditarietà statica limitata. Più sui limiti a breve. Questo pseudocodice mostra il valore:
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(){/*...*/};
}
Quindi ottieni:
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...
}
L'utilizzo è simile a:
// ...
MyStaticChild.Load(FileNamePath);
MyStaticChild.Save(FileNamePath);
doSomeThing(MyStaticChild.Payload.Attribute);
doSomething(MyStaticChild.AttributeBase);
doSomeThing(MyStaticChild.AttributeChild);
// ...
La persona che crea il figlio statico non deve pensare al processo di serializzazione fintanto che comprende eventuali limitazioni che potrebbero essere poste sul motore di serializzazione della piattaforma o dell'ambiente.
Le statistiche (singleton e altre forme di 'globali') spesso emergono dalla memoria di configurazione. L'ereditarietà statica consentirebbe a questo tipo di allocazione di responsabilità di essere rappresentata in modo chiaro nella sintassi in modo che corrisponda a una gerarchia di configurazioni. Tuttavia, come ho dimostrato, esiste un grande potenziale di ambiguità enorme se vengono implementati concetti di ereditarietà statica di base.
Credo che la scelta giusta per il progetto sarebbe quella di consentire l'ereditarietà statica con limiti specifici:
- Nessuna sostituzione di nulla. Il figlio non può sostituire gli attributi, i campi o i metodi di base, ... Il sovraccarico dovrebbe essere ok, purché ci sia una differenza nella firma che consenta al compilatore di sistemare il figlio rispetto alla base.
- Consenti solo basi statiche generiche, non puoi ereditare da una base statica non generica.
È comunque possibile modificare lo stesso negozio tramite un riferimento generico MyStaticBase<ChildPayload>.SomeBaseField
. Ma saresti scoraggiato poiché il tipo generico dovrebbe essere specificato. Mentre il riferimento bambino sarebbe più pulito: MyStaticChild.SomeBaseField
.
Non sono uno scrittore di compilatori, quindi non sono sicuro che mi manchi qualcosa sulle difficoltà di implementare queste limitazioni in un compilatore. Detto questo, sono fermamente convinto che vi sia una necessità di spazio informativo per un'eredità statica limitata e la risposta di base è che non è possibile a causa di una scelta di progettazione scadente (o troppo semplice).