Minha resposta: má escolha de design. ;-)
Este é um debate interessante focado no impacto da sintaxe. O núcleo do argumento, na minha opinião, é que uma decisão de design levou a classes estáticas seladas. Um foco na transparência dos nomes da classe estática aparecendo no nível superior em vez de se esconder ('confuso') atrás dos nomes filhos? Pode-se imaginar uma implementação de linguagem que poderia acessar diretamente a base ou a criança, confusa.
Um pseudo exemplo, assumindo que a herança estática foi definida de alguma forma.
public static class MyStaticBase
{
SomeType AttributeBase;
}
public static class MyStaticChild : MyStaticBase
{
SomeType AttributeChild;
}
levaria a:
// ...
DoSomethingTo(MyStaticBase.AttributeBase);
// ...
qual (impactaria) o mesmo armazenamento que
// ...
DoSomethingTo(MyStaticChild.AttributeBase);
// ...
Muito confuso!
Mas espere! Como o compilador lidaria com MyStaticBase e MyStaticChild com a mesma assinatura definida em ambos? Se o filho substitui o exemplo acima, NÃO mudaria o mesmo armazenamento, talvez? Isso leva a ainda mais confusão.
Acredito que haja uma forte justificativa de espaço informacional para herança estática limitada. Mais sobre os limites em breve. Este pseudocódigo mostra o valor:
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(){/*...*/};
}
Então você obtém:
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...
}
O uso se parece com:
// ...
MyStaticChild.Load(FileNamePath);
MyStaticChild.Save(FileNamePath);
doSomeThing(MyStaticChild.Payload.Attribute);
doSomething(MyStaticChild.AttributeBase);
doSomeThing(MyStaticChild.AttributeChild);
// ...
A pessoa que cria o filho estático não precisa pensar no processo de serialização, desde que entenda as limitações que possam ser colocadas no mecanismo de serialização da plataforma ou do ambiente.
As estáticas (singletons e outras formas de 'globais') surgem frequentemente em torno do armazenamento da configuração. A herança estática permitiria que esse tipo de alocação de responsabilidade seja representado de maneira limpa na sintaxe para corresponder a uma hierarquia de configurações. Embora, como mostrei, haja muito potencial para ambiguidade massiva se conceitos básicos de herança estática forem implementados.
Acredito que a escolha certa do projeto seria permitir a herança estática com limitações específicas:
- Nenhuma substituição de nada. O filho não pode substituir os atributos, campos ou métodos base, ... A sobrecarga deve estar ok, desde que haja uma diferença na assinatura que permita ao compilador classificar filho versus base.
- Permitir apenas bases estáticas genéricas, você não pode herdar de uma base estática não genérica.
Você ainda pode alterar a mesma loja por meio de uma referência genérica MyStaticBase<ChildPayload>.SomeBaseField
. Mas você ficaria desanimado, pois o tipo genérico precisaria ser especificado. Enquanto a referência criança seria mais limpo: MyStaticChild.SomeBaseField
.
Não sou um escritor de compilador, portanto, não tenho certeza se estou perdendo algo sobre as dificuldades de implementar essas limitações em um compilador. Dito isso, acredito firmemente que há um espaço informativo necessário para herança estática limitada e a resposta básica é que você não pode por causa de uma escolha de design pobre (ou muito simples).