"Classe abstrata" e "interface" são conceitos semelhantes, sendo a interface o mais abstrato dos dois. Um fator de diferenciação é que as classes abstratas fornecem implementações de métodos para classes derivadas quando necessário. No C #, no entanto, esse fator de diferenciação foi reduzido pela recente introdução de métodos de extensão, que permitem implementações para métodos de interface. Outro fator de diferenciação é que uma classe pode herdar apenas uma classe abstrata (ou seja, não há herança múltipla), mas pode implementar várias interfaces. Isso torna as interfaces menos restritivas e mais flexíveis. Então, em C #, quando devemos usar classes abstratas em vez de interfaces com métodos de extensão?
Um exemplo notável do modelo de método de interface + extensão é o LINQ, onde a funcionalidade de consulta é fornecida para qualquer tipo implementado IEnumerable
por meio de vários métodos de extensão.
fonte
Respostas:
Quando você precisar que uma parte da classe seja implementada. O melhor exemplo que usei é o padrão do método de modelo.
Assim, você pode definir as etapas que serão executadas quando Do () for chamado, sem saber as especificidades de como elas serão implementadas. As classes derivadas devem implementar os métodos abstratos, mas não o método Do ().
Os métodos de extensão não necessariamente atendem à parte "deve fazer parte da classe" da equação. Além disso, iirc, os métodos de extensão não podem (aparentemente) ter nada além de escopo público.
editar
A pergunta é mais interessante do que eu havia originalmente creditado. Após um exame mais aprofundado, Jon Skeet respondeu a uma pergunta como essa no SO em favor do uso de interfaces + métodos de extensão. Além disso, uma possível desvantagem é usar a reflexão contra uma hierarquia de objetos projetada dessa maneira.
Pessoalmente, estou tendo problemas para perceber o benefício de alterar uma prática comum atualmente, mas também vejo poucas ou nenhuma desvantagem em fazer isso.
Deve-se notar que é possível programar dessa maneira em vários idiomas através das classes Utility. As extensões apenas fornecem o açúcar sintático para fazer com que os métodos pareçam pertencer à classe.
fonte
Do()
serão definidos como um método de extensão. E os métodos deixados para a definição de classes derivadasDoThis()
serão membros da interface principal. E com interfaces, você pode suportar várias implementações / herança. E veja this-odetocode.com/blogs/scott/archive/2009/10/05/…É tudo sobre o que você deseja modelar:
Classes abstratas trabalham por herança . Sendo apenas classes base especiais, elas modelam alguma relação é uma relação.
Por exemplo, um cachorro é um animal, então temos
Como não faz sentido criar realmente um animal genérico (como seria?), Criamos essa
Animal
classe baseabstract
- mas ainda é uma classe base. E aDog
classe não faz sentido sem ser umaAnimal
.As interfaces, por outro lado, são uma história diferente. Eles não usam herança, mas fornecem polimorfismo (que também pode ser implementado com herança). Eles não modelam um relacionamento é-um , mas mais do que isso suporta .
Veja, por exemplo
IComparable
- um objeto que suporta ser comparado com outro .A funcionalidade de uma classe não depende das interfaces implementadas, a interface apenas fornece uma maneira genérica de acessar a funcionalidade. Ainda poderíamos fazer
Dispose
umGraphics
ou umFileStream
sem tê-los implementadosIDisposable
. A interface apenas relaciona os métodos.Em princípio, pode-se adicionar e remover interfaces como extensões, sem alterar o comportamento de uma classe, apenas enriquecendo o acesso a ela. Você não pode tirar uma classe base, pois o objeto se tornaria sem sentido!
fonte
Animal
abstrato. Isso permite que você escrevaabstract
funções para serem especializadas pelas classes derivadas. Ou mais em termos de programação - provavelmente não faz sentido criar aUserControl
, mas como aButton
é aUserControl
, temos o mesmo tipo de relacionamento de classe / classe básica.Acabei de perceber que não uso classes abstratas (pelo menos não criadas) há anos.
A classe abstrata é uma fera um tanto estranha entre interface e implementação. Há algo nas aulas abstratas que formiga meu senso de aranha. Eu diria que não se deve "expor" a implementação por trás da interface de nenhuma maneira (ou fazer quaisquer vínculos).
Mesmo se houver uma necessidade de comportamento comum entre as classes que implementam uma interface, eu usaria uma classe auxiliar independente, em vez de uma classe abstrata.
Eu iria para interfaces.
fonte
IMHO, acho que há uma mistura de conceitos aqui.
As classes usam um certo tipo de herança, enquanto as interfaces usam um tipo diferente de herança.
Ambos os tipos de herança são importantes e úteis, e cada um tem seus prós e contras.
Vamos começar no início.
A história com interfaces começa há muito tempo com C ++. Em meados da década de 1980, quando o C ++ foi desenvolvido, a idéia de interfaces como um tipo diferente de tipo ainda não era concretizada (chegaria a tempo).
O C ++ tinha apenas um tipo de herança, o tipo de herança usado pelas classes, chamado herança de implementação.
Para poder aplicar a recomendação do GoF Book: "Para programar para a interface, e não para a implementação", o C ++ suportou classes abstratas e herança múltipla de implementação para poder fazer quais interfaces em C # são capazes (e úteis!) De executar .
O C # apresenta um novo tipo de tipo, interfaces e um novo tipo de herança, a herança da interface, para oferecer pelo menos duas maneiras diferentes de oferecer suporte a "Programar para a interface e não para a implementação", com uma ressalva importante: somente C # suporta herança múltipla com herança de interface (e não com herança de implementação).
Portanto, os motivos arquitetônicos por trás das interfaces em C # são a recomendação do GoF.
Espero que isso possa ajudar.
Atenciosamente, Gastón
fonte
A aplicação de métodos de extensão a uma interface é útil para aplicar um comportamento comum entre classes que podem compartilhar apenas uma interface comum. Tais classes podem já existir e ser fechadas para extensões por outros meios.
Para novos projetos, eu preferiria o uso de métodos de extensão em interfaces. Para uma hierarquia de Tipos, os métodos de extensão fornecem um meio de estender o comportamento sem precisar abrir toda a hierarquia para modificação.
No entanto, os métodos de extensão não conseguem acessar a implementação privada, portanto, no topo de uma hierarquia, se eu precisar encapsular a implementação privada por trás de uma interface pública, uma classe abstrata seria a única maneira.
fonte
Eu acho que em C # herança múltipla não é suportada e é por isso que o conceito de interface é introduzido em C #.
No caso de classes abstratas, a herança múltipla também não é suportada. Portanto, é fácil decidir se as classes ou interfaces abstratas devem ser usadas.
fonte
Estou no processo de implementar uma classe Abstract no meu projeto simplesmente porque o C # não suporta operadores (conversões implícitas, no meu caso) em interfaces.
fonte