Eu tenho várias classes que realmente não precisam de nenhum estado. Do ponto de vista organizacional, eu gostaria de colocá-los em hierarquia.
Mas parece que não posso declarar herança para classes estáticas.
Algo parecido:
public static class Base
{
}
public static class Inherited : Base
{
}
não funciona.
Por que os designers da linguagem fecharam essa possibilidade?
c#
inheritance
static
Do utilizador
fonte
fonte
Respostas:
Citação a partir daqui :
Outras opiniões do channel9
E, como uma ideia valiosa, o littleguru tem uma "solução alternativa" parcial para esse problema: o padrão Singleton .
fonte
object
e todos devem saber disso. Portanto, as classes estáticas sempre são herdadasobject
, independentemente de você ser especificado explicitamente ou não.A principal razão pela qual você não pode herdar uma classe estática é que elas são abstratas e seladas (isso também impede que qualquer instância delas seja criada).
Então, é isso:
compila para este IL:
fonte
Pense desta maneira: você acessa membros estáticos através do nome do tipo, assim:
Para herdar dessa classe, você teria que acessá-la através do novo nome de tipo:
Portanto, o novo item não possui relações com o original quando usado no código. Não haveria como tirar proveito de qualquer relacionamento de herança para coisas como polimorfismo.
Talvez você esteja pensando em apenas estender alguns dos itens da classe original. Nesse caso, não há nada que o impeça de usar apenas um membro do original em um tipo totalmente novo.
Talvez você queira adicionar métodos a um tipo estático existente. Você pode fazer isso já através de métodos de extensão.
Talvez você queira passar uma estática
Type
para uma função em tempo de execução e chamar um método nesse tipo, sem saber exatamente o que o método faz. Nesse caso, você pode usar uma interface.Portanto, no final, você realmente não ganha nada com a herança de classes estáticas.
fonte
SomeClass<T> where T:Foo
possa acessar membrosFoo
e, se houverT
uma classe queFoo
substitua alguns membros estáticos virtuais , a classe genérica usará essas substituições. Provavelmente seria possível definir uma convenção através da qual os idiomas poderiam fazê-lo de maneira compatível com o CLR atual (por exemplo, uma classe com esses membros deve definir uma classe não estática protegida que contenha esses membros da instância, juntamente com um campo estático segurando uma instância desse tipo).O que você deseja obter usando a hierarquia de classes pode ser alcançado apenas através do namespace. Portanto, idiomas que suportam namespapces (como C #) não terão utilidade em implementar a hierarquia de classes de classes estáticas. Como você não pode instanciar nenhuma das classes, tudo o que você precisa é de uma organização hierárquica das definições de classe que você pode obter através do uso de namespaces
fonte
Você pode usar a composição ... isso permitirá acessar objetos de classe do tipo estático. Mas ainda não é possível implementar interfaces ou classes abstratas
fonte
Embora você possa acessar membros estáticos "herdados" por meio do nome de classes herdadas, os membros estáticos não são realmente herdados. Isso é em parte porque eles não podem ser virtuais ou abstratos e não podem ser substituídos. No seu exemplo, se você declarou um Base.Method (), o compilador mapeará uma chamada para Inherited.Method () de volta para Base.Method () de qualquer maneira. Você também pode chamar Base.Method () explicitamente. Você pode escrever um pequeno teste e ver o resultado com o Refletor.
Então ... se você não puder herdar membros estáticos e se as classes estáticas puderem conter apenas membros estáticos, que bem herdaria uma classe estática?
fonte
Hmmm ... seria muito diferente se você tivesse apenas classes não estáticas preenchidas com métodos estáticos ..?
fonte
Uma solução alternativa que você pode fazer é não usar classes estáticas, mas ocultar o construtor para que os membros estáticos das classes sejam a única coisa acessível fora da classe. O resultado é uma classe "estática" herdável essencialmente:
Infelizmente, devido à limitação de idioma "projetada", não podemos fazer:
fonte
Você pode fazer algo que se parecerá com herança estática.
Aqui está o truque:
Então você pode fazer isso:
A
Inherited
classe não é estática em si, mas não permitimos criá-la. Na verdade, ele herdou o construtor estático que constróiBase
e todas as propriedades e métodosBase
disponíveis como estáticos. Agora, a única coisa que resta a fazer é invólucros estáticos para cada método e propriedade que você precisa expor ao seu contexto estático.Existem desvantagens, como a necessidade de criação manual de métodos e
new
palavras - chave estáticos do wrapper . Mas essa abordagem ajuda a oferecer suporte a algo realmente semelhante à herança estática.PS Usamos isso para criar consultas compiladas e, na verdade, isso pode ser substituído pelo ConcurrentDictionary, mas um campo estático de somente leitura com sua segurança de thread era bom o suficiente.
fonte
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.
levaria a:
qual (impactaria) o mesmo armazenamento que
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:
Então você obtém:
O uso se parece com:
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:
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).
fonte
Classes estáticas e membros da classe são usados para criar dados e funções que podem ser acessados sem a criação de uma instância da classe. Os membros da classe estática podem ser usados para separar dados e comportamentos independentes de qualquer identidade de objeto: os dados e as funções não são alterados, independentemente do que acontece com o objeto. Classes estáticas podem ser usadas quando não há dados ou comportamento na classe que dependa da identidade do objeto.
Uma classe pode ser declarada estática, o que indica que ela contém apenas membros estáticos. Não é possível usar a nova palavra-chave para criar instâncias de uma classe estática. As classes estáticas são carregadas automaticamente pelo CLR (Common Language Runtime) do .NET Framework quando o programa ou espaço para nome que contém a classe é carregado.
Use uma classe estática para conter métodos que não estão associados a um objeto específico. Por exemplo, é um requisito comum criar um conjunto de métodos que não atuam nos dados da instância e não estão associados a um objeto específico no seu código. Você pode usar uma classe estática para armazenar esses métodos.
A seguir, estão os principais recursos de uma classe estática:
Eles contêm apenas membros estáticos.
Eles não podem ser instanciados.
Eles estão selados.
Eles não podem conter construtores de instância (Guia de Programação em C #).
Portanto, criar uma classe estática é basicamente o mesmo que criar uma classe que contém apenas membros estáticos e um construtor privado. Um construtor privado impede que a classe seja instanciada.
A vantagem de usar uma classe estática é que o compilador pode verificar para garantir que nenhum membro da instância seja adicionado acidentalmente. O compilador garantirá que instâncias dessa classe não possam ser criadas.
As classes estáticas são seladas e, portanto, não podem ser herdadas. Eles não podem herdar de nenhuma classe, exceto Object. Classes estáticas não podem conter um construtor de instância; no entanto, eles podem ter um construtor estático. Para obter mais informações, consulte Construtores estáticos (Guia de programação em C #).
fonte
Quando criamos uma classe estática que contém apenas os membros estáticos e um construtor privado. O único motivo é que o construtor estático impede que a classe seja instanciada, pelo que não podemos herdar uma classe estática. A única maneira de acessar o membro do classe estática usando o próprio nome da classe. Tente herdar uma classe estática não é uma boa ideia.
fonte