Ma réponse: mauvais choix de conception. ;-)
Il s'agit d'un débat intéressant axé sur l'impact syntaxique. À mon avis, l'essentiel de l'argument est qu'une décision de conception a conduit à des classes statiques scellées. Un accent sur la transparence des noms de classe statiques apparaissant au niveau supérieur au lieu de se cacher («confus») derrière les noms d'enfants? On peut imaginer une implémentation de langage qui pourrait accéder directement à la base ou à l'enfant, déroutant.
Un pseudo exemple, en supposant que l'héritage statique a été défini d'une manière ou d'une autre.
public static class MyStaticBase
{
SomeType AttributeBase;
}
public static class MyStaticChild : MyStaticBase
{
SomeType AttributeChild;
}
conduirait à:
// ...
DoSomethingTo(MyStaticBase.AttributeBase);
// ...
qui pourrait (aurait?) un impact sur le même stockage que
// ...
DoSomethingTo(MyStaticChild.AttributeBase);
// ...
Très perturbant!
Mais attendez! Comment le compilateur gérerait-il MyStaticBase et MyStaticChild ayant la même signature définie dans les deux? Si l'enfant remplace ce que mon exemple ci-dessus ne changerait PAS le même stockage, peut-être? Cela conduit à encore plus de confusion.
Je crois qu'il existe une forte justification de l'espace informationnel pour un héritage statique limité. Plus sur les limites sous peu. Ce pseudocode montre la valeur:
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(){/*...*/};
}
Vous obtenez alors:
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'utilisation ressemble à:
// ...
MyStaticChild.Load(FileNamePath);
MyStaticChild.Save(FileNamePath);
doSomeThing(MyStaticChild.Payload.Attribute);
doSomething(MyStaticChild.AttributeBase);
doSomeThing(MyStaticChild.AttributeChild);
// ...
La personne qui crée l'enfant statique n'a pas besoin de penser au processus de sérialisation tant qu'elle comprend les limitations qui pourraient être placées sur le moteur de sérialisation de la plateforme ou de l'environnement.
La statique (singletons et autres formes de «globaux») survient souvent autour du stockage de la configuration. L'héritage statique permettrait à ce type d'allocation de responsabilité d'être clairement représenté dans la syntaxe pour correspondre à une hiérarchie de configurations. Bien que, comme je l'ai montré, il existe de nombreuses possibilités d'ambiguïté massive si des concepts de base d'héritage statique sont mis en œuvre.
Je crois que le bon choix de conception serait de permettre l'héritage statique avec des limitations spécifiques:
- Aucune dérogation à quoi que ce soit. L'enfant ne peut pas remplacer les attributs de base, les champs ou les méthodes, ... La surcharge devrait être correcte, tant qu'il y a une différence de signature permettant au compilateur de trier l'enfant par rapport à la base.
- Autoriser uniquement les bases statiques génériques, vous ne pouvez pas hériter d'une base statique non générique.
Vous pouvez toujours changer le même magasin via une référence générique MyStaticBase<ChildPayload>.SomeBaseField
. Mais vous seriez découragé car le type générique devrait être spécifié. Alors que la référence de l' enfant serait plus propre: MyStaticChild.SomeBaseField
.
Je ne suis pas un écrivain de compilateur, donc je ne sais pas si je manque quelque chose sur les difficultés de mise en œuvre de ces limitations dans un compilateur. Cela dit, je crois fermement qu'il existe un besoin d'espace informationnel pour un héritage statique limité et la réponse de base est que vous ne pouvez pas en raison d'un choix de conception médiocre (ou trop simple).