Eu tenho uma classe com algumas funcionalidades padrão / compartilhadas. Eu uso abstract class
para isso:
public interface ITypeNameMapper
{
string Map(TypeDefinition typeDefinition);
}
public abstract class TypeNameMapper : ITypeNameMapper
{
public virtual string Map(TypeDefinition typeDefinition)
{
if (typeDefinition is ClassDefinition classDefinition)
{
return Map(classDefinition);
}
...
throw new ArgumentOutOfRangeException(nameof(typeDefinition));
}
protected abstract string Map(ClassDefinition classDefinition);
}
Como você pode ver, eu também tenho a interface ITypeNameMapper
. Faz sentido definir essa interface se eu já tenho uma classe abstrata TypeNameMapper
ou abstract class
é apenas o suficiente?
TypeDefinition
neste exemplo mínimo também é abstrato.
c#
interfaces
abstract-class
Konrad
fonte
fonte
Respostas:
Sim, porque o C # não permite herança múltipla, exceto com interfaces.
Portanto, se eu tiver uma classe que seja um TypeNameMapper e SomethingelseMapper, eu posso fazer:
fonte
ICanFly
,ICanRun
,ICanSwim
. Você precisa criar 8 classes de criatura, uma para cada combinação de características (YYY, YYN, YNY, ..., NNY, NNN). O SRP determina que você implemente cada comportamento (voe, corra, nade) uma vez e depois os implemente reutilizável nas 8 criaturas. A composição seria ainda melhor aqui, mas, ignorando a composição por um segundo, você já deve ver a necessidade de herdar / implementar vários comportamentos reutilizáveis separados devido ao SRP.interface
práticas ilícitas formais . Implementações redundantes que devem estar na base - que estão evoluindo de forma independente! O meu favorito: classes de 1 método, cada uma implementando seu próprio método 1interface
, cada uma com uma única instância. ... etc, etc, e etc #Interfaces e classes abstratas servem a diferentes propósitos:
No seu exemplo,
interface ITypeNameMapper
define as necessidades dos clientes eabstract class TypeNameMapper
não agrega nenhum valor.fonte
public
pertence ao cliente.TypeNameMapper
está agregando muito valor porque evita que o implementador escreva alguma lógica comum.interface
ou não é relevante apenas porque o C # proíbe a herança múltipla completa.Todo o conceito de interfaces foi criado para suportar uma família de classes com uma API compartilhada.
Isso está explicitamente dizendo que qualquer uso de uma interface implica que exista (ou se espera que exista) mais de uma implementação de sua especificação.
As estruturas de DI obscureceram as águas aqui, pois muitas delas exigem uma interface, mesmo que haja apenas uma implementação - para mim isso é uma sobrecarga irracional para o que, na maioria dos casos, é apenas um meio mais complexo e mais lento de chamar de novo, mas é o que é
A resposta está na própria pergunta. Se você tem uma classe abstrata, está se preparando para a criação de mais de uma classe derivada com uma API comum. Assim, o uso de uma interface é claramente indicado.
fonte
find ... -exec perl -pi -e ...
e possivelmente consertar erros triviais de compilação. O que quero dizerinterface
como código (você está falando sobre C # -interface
s, não como uma interface abstrata, como qualquer conjunto de classes / funções / etc), e a encerrasse "... mas ainda proibisse várias herança." Não há necessidade deinterface
s se você tiver MI.Se queremos responder explicitamente à pergunta, o autor diz: "Faz sentido definir essa interface se eu já tenho uma classe abstrata TypeNameMapper ou classe abstrata é apenas o suficiente?"
A resposta é sim e não - Sim, você deve criar a interface mesmo que já tenha a classe base abstrata (porque você não deve estar se referindo à classe base abstrata em nenhum código do cliente) e não, porque você não deveria ter criado a classe base abstrata na ausência de uma interface.
É evidente que você não pensou bastante na API que está tentando criar. Crie a API primeiro e forneça uma implementação parcial, se desejado. O fato de sua classe base abstrata digitar o código de verificação é suficiente para dizer que não é a abstração correta.
Como na maioria das coisas em OOD, quando você está no ritmo e seu modelo de objetos é bem executado, seu código o informará sobre o que vem a seguir. Comece com uma interface, implemente essa interface nas classes que você precisa. Se você estiver escrevendo código semelhante, extraia-o em uma classe base abstrata - é a interface que é importante, a classe base abstrata é apenas um auxiliar e pode haver mais de uma.
fonte
Isso é bastante difícil de responder sem conhecer o restante do aplicativo.
Supondo que você esteja usando algum tipo de modelo de DI e tenha projetado seu código para ser o mais extensível possível (para que você possa adicionar novos
TypeNameMapper
facilmente), eu diria que sim.Razões para:
interface
você não precisa se preocupar com isso em nenhuma implementação filhointerface
s. Embora muitos deles trabalhem com classes abstratas, isso nem sempre é um dado, e eu acredito muito em seguir o mesmo caminho que os outros 99% dos usuários de uma biblioteca sempre que possível.Razões contra:
class
/interface
mudar, haverá um pouco de sobrecarga adicionalTodas as coisas consideradas, eu diria que você deve criar o
interface
. As razões contra são bastante insignificantes, mas, embora seja possível usar resumos em zombaria e IoC, muitas vezes é muito mais fácil com interfaces. Em última análise, porém, eu não criticaria o código de um colega se ele seguisse o caminho contrário.fonte