Preciso usar uma interface quando apenas uma classe a implementar?

243

Não é o ponto principal de uma interface que várias classes aderem a um conjunto de regras e implementações?

Lamin Sanneh
fonte
16
Ou para facilitar a unittest.
11
Permitir que várias classes implementem interfaces e fazer com que seu código dependa das interfaces é essencial para o isolamento para teste de unidade. Se você estiver fazendo testes de unidade, terá outra classe implementando essa interface.
StuperUser
2
Reddit discussão sobre esta questão.
yannis
6
Os campos e métodos públicos são uma "interface" por si só. Se a falta de polimorfismo é intencionalmente planejada, não há razão para usar uma interface. O teste de unidade mencionado anteriormente é um uso planejado de polimorfismo.
mike30

Respostas:

205

A rigor, não, não, YAGNI se aplica. Dito isto, o tempo que você gastará criando a interface é mínimo, especialmente se você tiver uma ferramenta útil de geração de código fazendo a maior parte do trabalho para você. Se você não tem certeza se precisará ou não da interface, eu diria que é melhor errar no sentido de apoiar a definição de uma interface.

Além disso, o uso de uma interface mesmo para uma única classe fornecerá outra implementação simulada para testes de unidade, que não está em produção. A resposta de Avner Shahar-Kashtan se expande nesse ponto.

yannis
fonte
84
O teste com +1 significa que você quase sempre tem duas implementações
jk.
24
@YannisRizos Não concordo com seu último ponto por causa de Yagni. O acionamento de uma interface a partir de métodos públicos de classes é trivial após o fato, assim como a substituição do CFoo pelo IFoo nas classes de consumo. Não faz sentido escrevê-lo antes da necessidade.
9788 Dan Neely
5
Ainda não tenho certeza se estou seguindo seu raciocínio. Como as ferramentas de geração de código tornam a adição depois do fato ainda mais barata, vejo um motivo ainda menor para criar a interface antes que você tenha uma necessidade explícita.
Dan Neely
6
Eu acho que uma interface ausente não é um bom exemplo para o YAGNI, mas para uma "janela quebrada" e documentação ausente. Os usuários da classe são praticamente forçados a codificar contra a implementação, em vez da abstração como deveriam.
Fabio Fracassi
10
Por que você poluiria sua base de código com fragmentos sem sentido apenas para satisfazer alguma estrutura de teste? Sério, sou apenas um cara autodidata em JavaScript do lado do cliente, tentando descobrir se o WTF está errado com as implementações OOD em C # e Java developer que continuo encontrando na minha busca de me tornar um generalista completo, mas por que não ' eles tiram o IDE das suas mãos e não o permitem recuperá-lo até aprender a escrever um código legível e limpo quando o pegam fazendo esse tipo de coisa na faculdade? Isso é obsceno.
Erik Reppen
144

Eu responderia que se você precisa de uma interface ou não, não depende de quantas classes a implementarão. As interfaces são uma ferramenta para definir contratos entre vários subsistemas do seu aplicativo; então o que realmente importa é como seu aplicativo é dividido em subsistemas. Deve haver interfaces como o front-end para subsistemas encapsulados, não importa quantas classes os implementem.

Aqui está uma regra prática muito útil:

  • Se você faz com que a classe se Foorefira diretamente à classe BarImpl, você se compromete fortemente a mudar Footoda vez que muda BarImpl. Você basicamente os trata como uma unidade de código dividida em duas classes.
  • Se você se Fooreferir à interface Bar , está se comprometendo a evitar alterações Fooquando alterar BarImpl.

Se você definir interfaces nos pontos-chave do seu aplicativo, analise cuidadosamente os métodos que eles devem oferecer suporte e quais não devem e comenta claramente as interfaces para descrever como uma implementação deve se comportar (e como não), sua aplicação será muito mais fácil de entender porque essas interfaces comentadas irá fornecer uma espécie de especificação da aplicação, uma descrição de como ele está destinado a se comportar. Isso facilita muito a leitura do código (em vez de perguntar "o que diabos esse código deve fazer", você pode perguntar "como esse código faz o que deveria fazer").

Além de tudo isso (ou realmente por causa disso), as interfaces promovem compilação separada. Como as interfaces são triviais para compilar e têm menos dependências do que suas implementações, significa que se você escrever uma classe Foopara usar uma interface Bar, geralmente poderá recompilar BarImplsem precisar recompilar Foo. Em aplicativos grandes, isso pode economizar muito tempo.

sacundim
fonte
14
Eu votaria nisso muito mais de uma vez, se pudesse. A IMO é a melhor resposta para esta pergunta.
Fabio Fracassi
4
Se a classe está desempenhando apenas uma função (ou seja, teria apenas uma interface definida para ela), por que não fazer isso por métodos públicos / privados?
Matthew Finlay
4
1. Organização do código; Ter a interface em seu próprio arquivo, que possui apenas assinaturas e comentários da documentação, ajuda a manter o código limpo. 2. Estruturas que o forçam a expor métodos que você prefere manter privados (por exemplo, contêineres que injetam dependências por meio de setters públicos). 3. Compilação separada, como já mencionado; se a classe Foodepende da interface Bar, BarImplpode ser modificada sem precisar recompilar Foo. 4. Controle de acesso mais refinado do que ofertas públicas / privadas (exponha a mesma classe a dois clientes por meio de interfaces diferentes).
sacundim
3
E a última: 5. Os clientes (idealmente) não devem se importar com quantas classes meu módulo possui ou quantas, ou até mesmo podem contar. Tudo o que eles devem ver é um conjunto de tipos e algumas fábricas ou fachadas para fazer a bola rolar. Ou seja, muitas vezes vejo valor em encapsular mesmo em quais classes sua biblioteca consiste.
sacundim
4
@sacundim If you make class Foo refer directly to class BarImpl, you're strongly committing yourself to change Foo every time you change BarImplAo alterar o BarImpl, quais são as alterações que podem ser evitadas no Foo usando interface Bar? Desde que as assinaturas e a funcionalidade de um método não sejam alteradas no BarImpl, o Foo não exigirá alterações, mesmo sem a interface (o objetivo inteiro da interface). Eu estou falando sobre o cenário em que apenas uma classe ou seja, BarImplimplementa Bar. Para o cenário de várias classes, entendo o Princípio de Inversão de Dependência e como a interface é útil.
Shishir Gupta
101

As interfaces são designadas para definir um comportamento, isto é, um conjunto de protótipos de funções / métodos. Os tipos que implementam a interface implementam esse comportamento; portanto, quando você lida com esse tipo, sabe (em parte) qual é o comportamento dele.

Não há necessidade de definir uma interface se você souber que o comportamento definido por ela será usado apenas uma vez. BEIJO (mantenha-o simples, estúpido)

superM
fonte
Nem sempre, você pode usar a interface em uma classe se essa classe for genérica.
John Isaiah Carmona
Além disso, você pode introduzir uma interface quando finalmente for necessária facilmente no IDE moderno com uma refatoração de "interface de extração".
Hans-Peter Störr 13/08/2012
Considere uma classe de utilidade onde existem apenas métodos estáticos públicos e um construtor privado - perfeitamente aceitável e promovido por autores como Joshua Bloch et al.
Darrell Teague
63

Embora em teoria você não deva ter uma interface apenas para ter uma interface, a resposta de Yannis Rizos sugere outras complicações:

Quando você está escrevendo testes de unidade e usando estruturas simuladas, como Moq ou FakeItEasy (para nomear as duas mais recentes que usei), está criando implicitamente outra classe que implementa a interface. A pesquisa do código ou da análise estática pode afirmar que há apenas uma implementação, mas, de fato, há a implementação simulada interna. Sempre que você começar a escrever zombarias, verá que a extração de interfaces faz sentido.

Mas espere, tem mais. Existem mais cenários em que há implementações implícitas de interface. O uso da pilha de comunicação WCF do .NET, por exemplo, gera um proxy para um serviço remoto, que novamente implementa a interface.

Em um ambiente de código limpo, concordo com o restante das respostas aqui. No entanto, preste atenção em todas as estruturas, padrões ou dependências existentes que possam fazer uso de interfaces.

Avner Shahar-Kashtan
fonte
2
+1: Não tenho certeza se o YAGNI se aplica aqui, pois ter uma interface e usar estruturas (por exemplo, JMock, etc) que utilizam interfaces pode realmente economizar seu tempo.
Deco
4
@ Deco: boas estruturas de simulação (entre elas a JMock) nem precisam de interfaces.
22712 Michael Borgwardt
12
Criar uma interface apenas por causa de uma limitação de sua estrutura de zombaria parece um motivo terrível para mim. Usar, por exemplo, o EasyMock que zomba de uma classe é tão fácil quanto uma interface.
Alb
8
Eu diria que é o contrário. Usar objetos simulados no teste significa criar implementações alternativas para suas interfaces, por definição. Isso é verdade se você cria suas próprias classes FakeImplementation ou deixa estruturas de simulação fazer o trabalho pesado para você. Pode haver algumas estruturas, como o EasyMock, que usam vários hacks e truques de baixo nível para zombar de classes concretas - e mais poder para elas! - mas conceitualmente, objetos simulados são implementações alternativas a um contrato.
Avner Shahar-Kashtan
1
Você não está disparando os testes em produção. Por que um mock para uma classe que não precisa de uma interface, precisa de uma interface?
Erik Reppen
32

Não, você não precisa deles, e considero um antipadrão criar interfaces automaticamente para todas as referências de classe.

Existe um custo real para fazer Foo / FooImpl para tudo. O IDE pode criar a interface / implementação de graça, mas quando você está navegando no código, você tem uma carga cognitiva extra da F3 / F12 para foo.doSomething()levá-lo à assinatura da interface e não à implementação real desejada. Além disso, você tem a confusão de dois arquivos em vez de um para tudo.

Portanto, você deve fazê-lo apenas quando realmente precisar de algo.

Agora, abordando os contra-argumentos:

Preciso de interfaces para estruturas de injeção de dependência

As interfaces para suportar estruturas são herdadas. Em Java, as interfaces costumavam ser um requisito para proxies dinâmicos, pré-CGLIB. Hoje, você geralmente não precisa disso. É considerado progresso e um benefício para a produtividade do desenvolvedor que você não precisa mais deles no EJB3, Spring etc.

Preciso de zombaria para testes de unidade

Se você escreve suas próprias zombarias e tem duas implementações reais, uma interface é apropriada. Provavelmente não teríamos essa discussão em primeiro lugar se a sua base de código tivesse um FooImpl e um TestFoo.

Mas se você estiver usando uma estrutura de zombaria como Moq, EasyMock ou Mockito, poderá zombar de classes e não precisará de interfaces. É análogo à configuração foo.method = mockImplementationem um idioma dinâmico onde os métodos podem ser atribuídos.

Precisamos de interfaces para seguir o DIP (Dependency Inversion Principle)

O DIP diz que você constrói para depender de contratos (interfaces) e não de implementações. Mas uma classe é um contrato e uma abstração. É para isso que servem as palavras-chave públicas / privadas. Na universidade, o exemplo canônico era algo como uma classe Matrix ou Polynomial - os consumidores têm uma API pública para criar matrizes, adicioná-las etc., mas não têm permissão para se importar se a matriz for implementada de forma esparsa ou densa. Não havia IMatrix ou MatrixImpl necessário para provar esse ponto.

Além disso, o DIP geralmente é super aplicado em todos os níveis de chamada de classe / método, não apenas nos principais limites do módulo. Um sinal de que você está aplicando demais o DIP é que sua interface e implementação mudam na etapa de bloqueio, de modo que você precisa tocar em dois arquivos para fazer uma alteração em vez de em um. Se o DIP for aplicado adequadamente, isso significa que sua interface não precisa ser alterada com frequência. Além disso, outro sinal é que sua interface possui apenas um consumidor real (seu próprio aplicativo). História diferente se você estiver criando uma biblioteca de classes para consumo em muitos aplicativos diferentes.

Este é um corolário do argumento do tio Bob Martin sobre zombaria - você só precisa zombar das principais fronteiras da arquitetura. Em um aplicativo da web, o acesso HTTP e DB são os principais limites. Todas as chamadas de classe / método entre elas não são. O mesmo vale para o DIP.

Veja também:

wrschneider
fonte
4
Classes de zombaria em vez de interfaces (pelo menos em Java e C #) devem ser consideradas obsoletas, pois não há como impedir a execução do construtor da superclasse, o que pode fazer com que seu objeto simulado interaja com o ambiente de maneira não intencional. Zombar de uma interface é mais seguro e fácil, porque você não precisa pensar no código do construtor.
Jules
4
Não tive problemas com as classes de simulação, mas fiquei frustrado com a navegação do IDE que não estava funcionando conforme o esperado. Resolver um problema real supera um problema hipotético.
wrschneider
1
@Jules Você pode zombar de uma classe concreta, incluindo seu construtor em Java.
Assilias
1
@assylias como você evita que o construtor seja executado?
Jules
2
@Jules Depende da sua estrutura de zombaria - com o jmockit, por exemplo, você pode escrever new Mockup<YourClass>() {}e toda a classe, incluindo seus construtores, é zombada, seja uma interface, classe abstrata ou classe concreta. Você também pode "substituir" o comportamento do construtor, se desejar. Suponho que existem maneiras equivalentes no Mockito ou Powermock.
Assilias
22

Parece que as respostas dos dois lados da cerca podem ser resumidas no seguinte:

Projete bem e coloque interfaces onde as interfaces são necessárias.

Como observei em minha resposta à resposta de Yanni , acho que você nunca poderá ter uma regra rígida e rápida sobre interfaces. A regra precisa ser, por definição, flexível. Minha regra sobre interfaces é que uma interface deve ser usada em qualquer lugar em que você esteja criando uma API. E uma API deve ser criada em qualquer lugar em que você esteja cruzando a fronteira de um domínio de responsabilidade para outro.

Para um exemplo (terrivelmente artificial), digamos que você esteja criando uma Carclasse. Na sua turma, você certamente precisará de uma camada de interface do usuário. Neste exemplo em particular, que toma a forma de um IginitionSwitch, SteeringWheel, GearShift, GasPedal, e BrakePedal. Como este carro contém um AutomaticTransmission, você não precisa de um ClutchPedal. (E como este é um carro terrível, não há A / C, rádio ou assento. Na verdade, as tábuas do piso também estão faltando - você só precisa se segurar no volante e esperar o melhor!)

Então, qual dessas classes precisa de uma interface? A resposta pode ser todas elas, ou nenhuma delas - dependendo do seu design.

Você poderia ter uma interface parecida com esta:

Interface ICabin
    Event IgnitionSwitchTurnedOn()
    Event IgnitionSwitchTurnedOff()
    Event BrakePedalPositionChanged(int percent)
    Event GasPedalPositionChanged(int percent)
    Event GearShiftGearChanged(int gearNum)
    Event SteeringWheelTurned(float degree)
End Interface

Nesse ponto, o comportamento dessas classes se torna parte da interface / API do ICabin. Neste exemplo, as classes (se houver alguma) são provavelmente simples, com algumas propriedades e uma função ou duas. E o que você está dizendo implicitamente com seu design é que essas classes existem apenas para apoiar qualquer implementação concreta do ICabin que você tenha, e elas não podem existir por si mesmas ou são sem sentido fora do contexto da ICabin.

É o mesmo motivo pelo qual você não faz teste de unidade de membros particulares - eles existem apenas para oferecer suporte à API pública e, portanto, seu comportamento deve ser testado testando a API.

Portanto, se sua classe existe apenas para oferecer suporte a outra classe, e conceitualmente você a vê como realmente não tendo seu próprio domínio, não há problema em ignorar a interface. Mas se sua classe é importante o suficiente para que você considere que ela cresceu o suficiente para ter seu próprio domínio, vá em frente e faça uma interface.


EDITAR:

Frequentemente (incluindo nesta resposta), você lerá coisas como 'domínio', 'dependência' (frequentemente acopladas à 'injeção') que não significam nada para você quando você está começando a programar (elas com certeza não significa qualquer coisa para mim). Para domínio, significa exatamente o que parece:

O território sobre o qual domínio ou autoridade é exercido; as posses de uma soberana ou comunidade, ou algo semelhante. Também usado figurativamente. [WordNet sense 2] [1913 Webster]

Nos termos do meu exemplo - vamos considerar o IgnitionSwitch. Em um carro com espaço para carnes, o interruptor de ignição é responsável por:

  1. Autenticando (não identificando) o usuário (eles precisam da chave correta)
  2. Fornecer corrente ao motor de arranque para que possa ligar o carro
  3. Fornecer corrente ao sistema de ignição para que ele possa continuar operando
  4. Desligando a corrente para que o carro pare.
  5. Dependendo de como você o vê, na maioria dos carros (todos?) Mais recentes, existe um interruptor que impede que a chave seja removida da ignição enquanto a transmissão estiver fora do parque, portanto, isso pode fazer parte de seu domínio. (Na verdade, isso significa que preciso repensar e redesenhar meu sistema ...)

Essas propriedades compõem o domínio do IgnitionSwitch, ou em outras palavras, o que ele conhece e é responsável.

O IgnitionSwitchnão é responsável pelo GasPedal. O interruptor de ignição é completamente ignorante do pedal do acelerador em todos os sentidos. Os dois operam completamente independentes um do outro (embora um carro não tenha valor algum sem os dois!).

Como afirmei originalmente, isso depende do seu design. Você pode criar um IgnitionSwitchque tenha dois valores: Ativado ( True) e Desativado ( False). Ou você pode projetá-lo para autenticar a chave fornecida e uma série de outras ações. Essa é a parte mais difícil de ser desenvolvedor: decidir onde traçar as linhas na areia - e honestamente na maioria das vezes é completamente relativo. Porém, essas linhas na areia são importantes - é onde está sua API e, portanto, onde devem estar suas interfaces.

Wayne Werner
fonte
Você poderia elaborar mais sobre o que você quer dizer com "ter seu próprio domínio"?
Lamin Sanneh
1
@LaminSanneh, elaborado. Isso ajuda?
Wayne Werner
8

Não (YAGNI) , a menos que você esteja planejando escrever testes para outras classes usando essa interface, e esses testes se beneficiariam de zombar da interface.

stijn
fonte
8

Do MSDN :

As interfaces são mais adequadas para situações em que seus aplicativos requerem muitos tipos de objetos possivelmente não relacionados para fornecer determinadas funcionalidades.

As interfaces são mais flexíveis que as classes base, porque você pode definir uma única implementação que pode implementar várias interfaces.

As interfaces são melhores em situações nas quais você não precisa herdar a implementação de uma classe base.

As interfaces são úteis nos casos em que você não pode usar a herança de classe. Por exemplo, estruturas não podem herdar de classes, mas podem implementar interfaces.

Geralmente, no caso de uma única classe, não será necessário implementar uma interface, mas, considerando o futuro do seu projeto, pode ser útil definir formalmente o comportamento necessário das classes.

lwm
fonte
5

Para responder à pergunta: Há mais do que isso.

Um aspecto importante de uma interface é a intenção.

Uma interface é "um tipo abstrato que não contém dados, mas expõe comportamentos" - Interface (computação) Portanto, se esse é um comportamento ou um conjunto de comportamentos que a classe suporta, então uma interface provavelmente é o padrão correto. Se, no entanto, o (s) comportamento (s) é (são) intrínseco (s) ao conceito incorporado pela classe, é provável que você não deseje uma interface.

A primeira pergunta a fazer é qual é a natureza da coisa ou processo que você está tentando representar. Em seguida, prossiga com as razões práticas para implementar essa natureza de uma determinada maneira.

Joshua Drake
fonte
5

Desde que você fez essa pergunta, suponho que você já tenha visto o interesse de ter uma interface oculta várias implementações. Isso pode ser manifestado pelo princípio de inversão de dependência.

No entanto, a necessidade de ter ou não uma interface não depende do número de suas implementações. O verdadeiro papel de uma interface é que ela define um contrato informando qual serviço deve ser fornecido, em vez de como deve ser implementado.

Uma vez definido o contrato, duas ou mais equipes podem trabalhar de forma independente. Digamos que você esteja trabalhando em um módulo A e dependa do módulo B, o fato de criar uma interface em B permite continuar seu trabalho sem se preocupar com a implementação de B, porque todos os detalhes estão ocultos pela interface. Assim, a programação distribuída se torna possível.

Embora o módulo B tenha apenas uma implementação de sua interface, a interface ainda é necessária.

Em conclusão, uma interface oculta detalhes de implementação de seus usuários. A programação da interface ajuda a escrever mais documentos, pois é necessário definir um contrato, escrever um software mais modular, promover testes de unidade e acelerar a velocidade de desenvolvimento.

Hui Wang
fonte
2
Toda classe pode ter uma interface pública (os métodos públicos) e uma interface privada (os detalhes da implementação). Eu poderia argumentar que a interface pública da classe é o contrato. Você não precisa de um elemento extra para trabalhar nesse contrato.
21414 Fuhrmanator
4

Todas as respostas aqui são muito boas. Na verdade, na maioria das vezes você não precisa implementar uma interface diferente. Mas há casos em que você pode querer fazê-lo de qualquer maneira. Aqui está um caso em que eu faço:

A classe implementa outra interface que eu não quero expor
Happen frequentemente com a classe do adaptador que une o código de terceiros.

interface NameChangeListener { // Implemented by a lot of people
    void nameChanged(String name); 
} 

interface NameChangeCount { // Only implemented by my class
    int getCount();
}

class NameChangeCounter implements NameChangeListener, NameChangeCount {
    ...
}

class SomeUserInterface {
    private NameChangeCount currentCount; // Will never know that you can change the counter
}

A classe usa uma tecnologia específica que não deve vazar na
maioria das vezes ao interagir com bibliotecas externas. Mesmo se houver apenas uma implementação, eu uso uma interface para garantir que eu não introduza acoplamentos desnecessários com a biblioteca externa.

interface SomeRepository { // Guarantee that the external library details won't leak trough
    ...
}

class OracleSomeRepository implements SomeRepository { 
    ... // Oracle prefix allow us to quickly know what is going on in this class
}

Comunicação entre camadas
Mesmo que apenas uma classe de interface do usuário implemente uma da classe de domínio, ela permite uma melhor separação entre essas camadas e, o mais importante, evita a dependência cíclica.

package project.domain;

interface UserRequestSource {
    public UserRequest getLastRequest();
}

class UserBehaviorAnalyser {
    private UserRequestSource requestSource;
}

package project.ui;

class OrderCompleteDialog extends SomeUIClass implements project.domain.UserRequestSource {
    // UI concern, no need for my domain object to know about this method.
    public void displayLabelInErrorMode(); 

    // They most certainly need to know about *that* though
    public UserRequest getLastRequest();
}

Somente um subconjunto do método deve estar disponível para a maioria dos objetos.
Principalmente acontece quando tenho algum método de configuração na classe concreta

interface Sender {
    void sendMessage(Message message)
}

class PacketSender implements Sender {
    void sendMessage(Message message);
    void setPacketSize(int sizeInByte);
}

class Throttler { // This class need to have full access to the object
    private PacketSender sender;

    public useLowNetworkUsageMode() {
        sender.setPacketSize(LOW_PACKET_SIZE);
        sender.sendMessage(new NotifyLowNetworkUsageMessage());

        ... // Other details
    }
}

class MailOrder { // Not this one though
    private Sender sender;
}

Portanto, no final, uso a interface pelo mesmo motivo que uso o campo privado: outro objeto não deve ter acesso a coisas que não deve acessar. Se eu tiver um caso como esse, apresento uma interface mesmo que apenas uma classe a implemente.

Laurent Bourgault-Roy
fonte
2

As interfaces são realmente importantes, mas tente controlar o número delas que você possui.

Depois de criar interfaces para praticamente tudo, é fácil acabar com o código de 'espaguete picado'. Apresento a maior sabedoria de Ayende Rahien, que publicou algumas palavras muito sábias sobre o assunto:

http://ayende.com/blog/153889/limit-your-abstractions-analyzing-a-ddd-application

Este é o primeiro post de uma série inteira, então continue lendo!

Lord Spa
fonte
código 'spaghetti picado' também é conhecido como código ravioli c2.com/cgi/wiki?RavioliCode
CurtainDog 7/12
Parece-me mais com código de lasanha ou código de baklava - código com muitas camadas. ;-)
dodgy_coder 8/08/12
2

Um motivo pelo qual você ainda pode querer introduzir uma interface nesse caso é seguir o Princípio de Inversão de Dependência . Ou seja, o módulo que usa a classe dependerá de uma abstração (ou seja, da interface) em vez de depender de uma implementação concreta. Separa os componentes de alto nível dos componentes de baixo nível.

dodgy_coder
fonte
2

Não há motivo real para fazer qualquer coisa. As interfaces são para ajudá-lo e não o programa de saída. Portanto, mesmo que a Interface seja implementada por um milhão de classes, não há regra que diga que você deve criar uma. Você cria um para que, quando você ou qualquer outra pessoa que use seu código, deseje alterar algo que se aplica a todas as implementações. Criar uma interface ajudará você em todos os casos futuros em que você queira criar outra classe que a implemente.

John Demetriou
fonte
1

Nem sempre é necessário definir uma interface para uma classe.

Objetos simples, como objetos de valor, não têm várias implementações. Eles também não precisam ser ridicularizados. A implementação pode ser testada por si só e quando outras classes são testadas que dependem delas, o objeto de valor real pode ser usado.

Lembre-se de que criar uma interface tem um custo. Ele precisa ser atualizado ao longo da implementação, precisa de um arquivo extra e algum IDE terá problemas ao aplicar zoom na implementação, não na interface.

Então, eu definiria interfaces apenas para classes de nível superior, nas quais você deseja uma abstração da implementação.

Observe que com uma classe você obtém uma interface gratuitamente. Além da implementação, uma classe define uma interface do conjunto de métodos públicos. Essa interface é implementada por todas as classes derivadas. Não é estritamente falando uma interface, mas pode ser usada exatamente da mesma maneira. Portanto, não creio que seja necessário recriar uma interface que já exista sob o nome da classe.

Florian F
fonte