Ultimamente, tenho trabalhado com fornecedores bastante, e me deparei com uma situação interessante em que queria ter uma classe abstrata que tivesse um método estático abstrato. Li alguns posts sobre o assunto, e isso meio que fazia sentido, mas há uma boa explicação clara?
c#
.net
language-design
lomaxx
fonte
fonte
Respostas:
Os métodos estáticos não são instanciados como tal, apenas estão disponíveis sem uma referência a objeto.
Uma chamada para um método estático é feita através do nome da classe, não através de uma referência a objeto, e o código da Linguagem Intermediária (IL) para chamá-lo chamará o método abstrato pelo nome da classe que a definiu, não necessariamente pelo nome de a classe que você usou.
Deixe-me mostrar um exemplo.
Com o seguinte código:
Se você chamar B.Test, assim:
Em seguida, o código real dentro do método Main é o seguinte:
Como você pode ver, a chamada é feita para A.Test, porque foi a classe A que a definiu, e não para B.Test, mesmo que você possa escrever o código dessa maneira.
Se você tivesse tipos de classe , como no Delphi, onde você pode criar uma variável referente a um tipo e não a um objeto, teria mais utilidade para métodos estáticos virtuais e, portanto, abstratos (e também construtores), mas eles não estão disponíveis e portanto, as chamadas estáticas não são virtuais no .NET.
Percebo que os designers de IL podem permitir que o código seja compilado para chamar B.Test e resolver a chamada em tempo de execução, mas ainda assim não seria virtual, pois você ainda teria que escrever algum tipo de nome de classe lá.
Métodos virtuais e, portanto, abstratos, são úteis apenas quando você está usando uma variável que, em tempo de execução, pode conter muitos tipos diferentes de objetos e, portanto, você deseja chamar o método correto para o objeto atual que você possui na variável. Com os métodos estáticos, você precisa passar pelo nome de uma classe de qualquer maneira; portanto, o método exato a ser chamado é conhecido no momento da compilação, porque não pode e não muda.
Portanto, métodos estáticos virtuais / abstratos não estão disponíveis no .NET.
fonte
Test()
éA
mais do que abstrata e potencialmente definida emB
. \Car
tipo com umCreateFromDescription
método de fábrica estática virtual , o código que aceitasse umCar
tipo genérico restritoT
poderia chamarT.CreateFromDescription
para produzir um carro do tipoT
. Essa construção poderia ser suportada muito bem no CLR se cada tipo que definisse esse método contivesse uma instância estática singleton de uma classe aninhada genérica que contivesse os métodos virtuais "estáticos".Os métodos estáticos não podem ser herdados ou substituídos, e é por isso que eles não podem ser abstratos. Como os métodos estáticos são definidos no tipo, e não na instância, de uma classe, eles devem ser chamados explicitamente nesse tipo. Portanto, quando você quiser chamar um método em uma classe filho, precisará usar o nome para chamá-lo. Isso torna a herança irrelevante.
Suponha que você possa, por um momento, herdar métodos estáticos. Imagine este cenário:
Se você chamar Base.GetNumber (), qual método seria chamado? Qual valor retornou? É muito fácil perceber que, sem criar instâncias de objetos, a herança é bastante difícil. Métodos abstratos sem herança são apenas métodos que não têm um corpo, portanto não podem ser chamados.
fonte
int DoSomething<T>() where T:Base {return T.GetNumber();}
. Seria útil seDoSomething<Base>()
pudesse retornar cinco, enquantoDoSomething<Child2>()
retornaria dois. Essa capacidade seria útil não apenas para exemplos de brinquedos, mas também para algo comoclass Car {public static virtual Car Build(PurchaseOrder PO);}
, onde todas as classes derivadasCar
teriam que definir um método que pudesse criar uma instância para um pedido de compra.Outro entrevistado (McDowell) disse que o polimorfismo funciona apenas para instâncias de objetos. Isso deve ser qualificado; existem idiomas que tratam as classes como instâncias do tipo "Classe" ou "Metaclasse". Essas linguagens suportam polimorfismo para os métodos de instância e classe (estático).
C #, como Java e C ++ antes, não é uma linguagem; a
static
palavra-chave é usada explicitamente para indicar que o método está vinculado estaticamente em vez de dinâmico / virtual.fonte
Aqui está uma situação em que há definitivamente uma necessidade de herança para campos e métodos estáticos:
fonte
legs
deve ser uma propriedade abstrata estática.Para adicionar às explicações anteriores, as chamadas de método estático são vinculadas a um método específico em tempo de compilação , que exclui o comportamento polimórfico.
fonte
Na verdade, substituímos os métodos estáticos (no delphi), é um pouco feio, mas funciona perfeitamente para as nossas necessidades.
Nós o usamos para que as classes possam ter uma lista de seus objetos disponíveis sem a instância da classe; por exemplo, temos um método parecido com este:
É feio, mas necessário; dessa maneira, podemos instanciar exatamente o que é necessário, em vez de ter todas as classes instanciadas apenas para procurar os objetos disponíveis.
Este foi um exemplo simples, mas o aplicativo em si é um aplicativo cliente-servidor que possui todas as classes disponíveis em apenas um servidor e vários clientes diferentes que podem não precisar de tudo o que o servidor possui e nunca precisarão de uma instância de objeto.
Portanto, isso é muito mais fácil de manter do que ter um aplicativo de servidor diferente para cada cliente.
Espero que o exemplo esteja claro.
fonte
Os métodos abstratos são implicitamente virtuais. Métodos abstratos requerem uma instância, mas métodos estáticos não têm uma instância. Portanto, você pode ter um método estático em uma classe abstrata, apenas não pode ser abstrato estático (ou abstrato estático).
fonte