Por que as interfaces são úteis?

158

Eu tenho estudado e codificado em C # há algum tempo. Mas, ainda assim, não consigo entender a utilidade das interfaces. Eles trazem muito pouco para a mesa. Além de fornecer as assinaturas da função, eles não fazem nada. Se me lembro dos nomes e assinaturas das funções que precisam ser implementadas, não há necessidade delas. Eles estão lá apenas para garantir que as funções mencionadas (na interface) sejam implementadas na classe herdada.

O C # é uma linguagem excelente, mas às vezes dá a sensação de que primeiro a Microsoft cria o problema (não permitindo herança múltipla) e depois fornece a solução, que é bastante entediante.

Esse é o meu entendimento, que se baseia em experiência limitada em codificação. Qual sua opinião sobre as interfaces? Quantas vezes você faz uso deles e o que o faz?

Pankaj Upadhyay
fonte
55
"Se eu me lembro dos nomes e assinaturas das funções que precisam ser implementadas, não há necessidade delas". Essa afirmação me faz suspeitar que você deva examinar um pouco mais as vantagens das linguagens estaticamente tipadas .
Steven Jeuris
37
Esqueça o C #, esqueça o Java, esqueça a linguagem. É simplesmente pensar em termos de OO. Gostaria de encorajá-lo a pegar algum material de leitura de pessoas como Robert C. Martin, Martin Fowler, Michael Feathers, Gang of Four, etc., pois isso ajudará a expandir seu pensamento.
Anthony Pegram
27
Levei mais de dois anos para realmente entender para que servem as interfaces. Minha sugestão: estudar Design Patterns. Como a maioria deles depende de interfaces, você entenderá rapidamente por que são tão úteis.
Oliver Weiler
37
Você tem muito a aprender amigo.
ChaosPandion
60
@ChaosPandion todos temos muito a aprender
kenwarner

Respostas:

151

Eles estão lá apenas para garantir que as funções mencionadas (na interface) sejam implementadas na classe herdada.

Corrigir. Esse é um benefício suficientemente impressionante para justificar o recurso. Como outros já disseram, uma interface é uma obrigação contratual de implementar certos métodos, propriedades e eventos. O benefício atraente de uma linguagem de tipo estaticamente é que o compilador pode verificar se um contrato em que o seu código depende é realmente cumprido.

Dito isto, as interfaces são uma maneira bastante fraca de representar obrigações contratuais. Se você deseja uma maneira mais forte e flexível de representar obrigações contratuais, consulte o recurso Contratos de código fornecido com a última versão do Visual Studio.

O C # é uma linguagem excelente, mas às vezes dá a sensação de que primeiro a Microsoft cria o problema (não permitindo herança múltipla) e depois fornece a solução, que é bastante tediosa.

Bem, eu estou feliz que você goste.

Todos os projetos complexos de software resultam da ponderação de recursos conflitantes e da tentativa de encontrar o "ponto ideal" que oferece grandes benefícios por pequenos custos. Aprendemos por experiência dolorosa que idiomas que permitem herança múltipla para fins de compartilhamento de implementação têm benefícios relativamente pequenos e custos relativamente altos. A permissão de herança múltipla apenas em interfaces, que não compartilham detalhes de implementação, oferece muitos dos benefícios da herança múltipla sem a maioria dos custos.

Eric Lippert
fonte
Eu estava lendo "A Microsoft cria o problema ao não permitir herança múltipla" e pensei que Eric Lippert teria algo a dizer sobre isso.
configurator
Mais relevante para esta resposta: Eric, você está referindo o solicitante aos contratos de código, mas eles são lamentavelmente incompletos; nada além dos contratos mais básicos não é aplicável pelo verificador estático. Eu tentei usar o Code Contract em um pequeno projeto; Adicionei centenas de linhas para cada método, especificando tudo o que pude sobre entrada e saída e, no entanto, tive que adicionar muitas Assumechamadas, para casos como membros de matriz ou enumeração. Depois de adicionar tudo e ver a bagunça estaticamente verificada que eu tinha, voltei ao controle de origem porque reduziu a qualidade do meu projeto.
configurator
17
@ configurador: Eles estão incompletos porque não podem ser completos; a verificação estática do programa com contratos arbitrários equivale a resolver o problema da parada. (Por exemplo, você pode escrever um contrato de código que diga que os argumentos de um método devem ser um contraexemplo do Último Teorema de Fermat; mas o verificador estático não poderá verificar se não existem argumentos desse tipo.) deve usá-lo criteriosamente se você espera que o verificador estático conclua seu trabalho antes da morte pelo calor do universo. (Se a sua reclamação é que o BCL não está suficientemente anotada: Eu concordo.)
Eric Lippert
2
Espero que perceba que, quando um método promete que a matriz ou enumeração de resultados não contém nulo, o método using pode usar os valores em locais que não permitem nulos. Essa é a única coisa que eu esperava que fizesse e não era importante, e era importante demais para ser utilizável sem ela; qualquer outra coisa é apenas um bônus. Dito isso, sei que a verificação estática não pode ser concluída, e é por isso que acho que não é uma boa alternativa confiar nos contratos.
configurator
9
+1 em "Bem, estou feliz que você tenha gostado". E todas as outras coisas também.
Robert S.
235

insira a descrição da imagem aqui

Portanto, neste exemplo, o PowerSocket não sabe mais nada sobre os outros objetos. Todos os objetos dependem da energia fornecida pelo PowerSocket, para que eles implementem o IPowerPlug e, assim, possam se conectar a ele.

As interfaces são úteis porque fornecem contratos que os objetos podem usar para trabalhar juntos sem a necessidade de saber mais sobre eles.

Slomojo
fonte
4
O objeto parte inferior esquerda não se parece com ele implementa IPowerPlug =)
Steven Striga
100
Porra, mas teremos que usar um padrão de adaptador para usar o IPowerPlug em diferentes países!
Steven Jeuris
A instalação fraudulenta de um dispositivo para contornar a interface não é segura (mas algumas pessoas ainda o fazem citando o desempenho como uma desculpa não testada) e provavelmente levando a incêndios.
YoungJohn
4
Esta resposta é simplesmente incrível ...
Mario Garcia
Apenas apontar esta resposta não diz - neste exemplo em particular - por que usar uma interface seria preferível à herança. Alguém novo em interfaces pode perguntar por que eles não herdam apenas, por exemplo, MainsPoweredDevice, que fornece toda a funcionalidade do plug, com o soquete aceitando qualquer coisa derivada de MainsPoweredDevice.
ingrediente_15939
145

Além de fornecer as assinaturas da função, eles não fazem nada. Se me lembro dos nomes e assinaturas das funções que precisam ser implementadas, não há necessidade delas.

O objetivo das interfaces não é ajudá-lo a se lembrar de qual método implementar, está aqui para definir um contrato . No exemplo foreach P.Brian.Mackey (que acaba errado , mas não nos importamos), IEnumerable define um contrato entre foreach e qualquer coisa enumerável. Ele diz: "Seja você quem for, desde que cumpra o contrato (implemente o IEnumerable), prometo que vou repetir todos os seus elementos". E isso é ótimo (para uma linguagem não dinâmica).

Graças às interfaces, você pode obter um acoplamento muito baixo entre duas classes.

David
fonte
Não gosto de usar o termo "digitação de pato" porque significa coisas diferentes para pessoas diferentes. Usamos a correspondência de padrões para o loop "foreach" porque, quando foi projetado, IEnumerable <T> estava indisponível. Usamos a correspondência de padrões para o LINQ porque o sistema do tipo C # é muito fraco para capturar o "padrão de mônada" necessário; você precisaria de algo como o sistema do tipo Haskell.
Eric Lippert
@ Eric: "correspondência de padrão" não tem o mesmo problema? Quando o ouço, penso em F # / Scala / Haskell. Mas acho que é uma ideia mais ampla do que digitar patos.
Daniel
@ Daniel: Sim, acho que sim. É seis de uma e meia dúzia das outras, eu acho!
Eric Lippert
36

As interfaces são a melhor maneira de manter construções bem dissociadas.

Ao escrever testes, você descobrirá que classes concretas não funcionarão em seu ambiente de teste.

Exemplo: você deseja testar uma classe que depende de uma classe do Serviço de Acesso a Dados . Se essa classe estiver conversando com um serviço da Web ou banco de dados - seu teste de unidade não será executado em seu ambiente de teste (além de ter se transformado em um teste de integração).

Solução? Use uma interface para o serviço de acesso a dados e zombe dessa interface para poder testar sua classe como uma unidade.

Por outro lado, o WPF e o Silverlight não tocam nada com o Interfaces quando se trata de encadernação. Esta é uma ruga bastante desagradável.

Sheldon Warkentin
fonte
2
Ouça ouça! As interfaces foram inventadas para resolver outros problemas, como o polimorfismo. No entanto, para mim, eles se destacam ao implementar um padrão de injeção de dependência.
Andy
29

As interfaces são a espinha dorsal do polimorfismo (estático)! A interface é o que importa. A herança não funcionaria sem interfaces, pois as subclasses basicamente herdam a interface já implementada do pai.

Quantas vezes você faz uso deles e o que faz você fazer isso?

Com bastante frequência. Tudo o que precisa ser plugável é uma interface em meus aplicativos. Muitas vezes, você tem classes não relacionadas que precisam fornecer o mesmo comportamento. Você não pode resolver esses problemas com herança.

Precisa de algoritmos diferentes para executar operações nos mesmos dados? Use uma interface ( veja padrão de estratégia )!

Deseja usar diferentes implementações de lista? Codifique contra uma interface e o chamador não precisa se preocupar com a implementação!

Foi considerado uma boa prática (não apenas no OOP) codificar contra interfaces por muito tempo, por um único motivo: é fácil alterar uma implementação quando você percebe que ela não atende às suas necessidades. É bastante complicado se você tentar conseguir isso apenas com herança múltipla ou se resumir à criação de classes vazias para fornecer a interface necessária.

Falcon
fonte
1
Nunca ouviu falar de polimorfia, você quer dizer polimorfismo?
Steven Jeuris
1
Dito isto, se a Microsoft permitiu que a herança múltipla, em primeiro lugar, não teria havido nenhuma razão para a existência de interfaces
Pankaj Upadhyay
10
@Pankaj Upadhyay: herança múltipla e interfaces são dois pares de sapatos diferentes. E se você precisar de uma interface de duas classes não relacionadas com comportamento diferente? Você não pode resolver isso por herança múltipla. Você precisa implementá-lo separadamente de qualquer maneira. E então você precisará de algo para descrever a interface, a fim de fornecer um comportamento polimórfico. A herança múltipla é um beco sem saída para andar em muitos casos, e é muito fácil dar um tiro no pé mais cedo ou mais tarde.
Falcon
1
Vamos simplificar. Se minha interface implementa duas funções Display e Comment, e eu tenho uma classe que as implementa. Por que não removo a interface e uso as funções diretamente. O que estou dizendo é que eles estão apenas fornecendo os nomes das funções que precisam ser implementadas. Se alguém pode se lembrar essas funções, então por que criar uma interface
Pankaj Upadhyay
9
@Pankaj, se é para isso que você precisa da interface, não a use. Você usa uma interface quando possui um programa que deseja ignorar todos os aspectos da classe e acessá-lo por seu tipo base, isto é, a interface. Eles não precisam conhecer nenhuma das subclasses, apenas que é do tipo da interface. Dessa forma, você pode chamar o método implementado da subclasse por meio da referência à interface do objeto. Isso é herança básica e material de design. Sem ele, você também pode usar C. Mesmo que não o use explicitamente, a estrutura não funcionaria sem ele.
Jonathan Henson
12

Você provavelmente já usou foreache achou uma ferramenta de iteração bastante útil. Você sabia que ele requer uma interface para funcionar, IEnumerable ?

Esse é certamente um caso concreto falando da utilidade de uma interface.

P.Brian.Mackey
fonte
5
Na verdade, o foreach não requer IEnumerable: msdn.microsoft.com/en-us/library/9yb8xew9%28VS.80%29.aspx
Matt H
1
Eu estudei tudo isso, mas é como segurar a orelha com a outra mão. Se a herança múltipla fosse permitida, a interface teria sido uma escolha distante.
Pankaj Upadhyay
2
As interfaces são herança múltipla, algo que muitas vezes é esquecido. No entanto, eles não permitem herança múltipla de comportamento e estado. Mixins ou traços permitem herança múltipla de comportamento, mas não estado compartilhado que causa problemas: en.wikipedia.org/wiki/Mixin
Matt H
@Pankaj, offtopic, mas você se importa se eu perguntar qual é o seu idioma nativo? "Segurando a orelha com a outra mão" é um ótimo idioma e fiquei curioso de onde vem.
Kevin
3
@Iceman. LOL .... eu sou da Índia. E aqui está um idioma comum que reflete fazer coisas fáceis da maneira mais difícil.
Pankaj Upadhyay
11

As interfaces são para codificar objetos como um plugue para a fiação doméstica. Você soldaria seu rádio diretamente na fiação da sua casa? E o seu aspirador? Claro que não. O plugue e a tomada em que ele se encaixa formam a "interface" entre a fiação da sua casa e o dispositivo que precisa da energia. A fiação da sua casa não precisa saber nada sobre o dispositivo além de usar um plugue aterrado de três pinos e requer energia elétrica a 120VAC <= 15A. Por outro lado, o dispositivo não requer nenhum conhecimento misterioso de como sua casa é conectada, exceto que possui uma ou mais tomadas de três pinos convenientemente localizadas que fornecem 120VAC <= 15A.

As interfaces executam uma função muito semelhante no código. Um objeto pode declarar que uma variável, parâmetro ou tipo de retorno específico é de um tipo de interface. A interface não pode ser instanciada diretamente com uma newpalavra - chave, mas meu objeto pode receber ou encontrar a implementação dessa interface com a qual ele precisará trabalhar. Uma vez que o objeto tem sua dependência, ele não precisa saber exatamente o que é essa dependência, apenas precisa saber que pode chamar os métodos X, Y e Z na dependência. As implementações da interface não precisam saber como serão usadas, apenas precisam saber que é esperado que forneçam os métodos X, Y e Z com assinaturas específicas.

Assim, abstraindo vários objetos atrás da mesma interface, você fornece um conjunto comum de funcionalidades para qualquer consumidor de objetos dessa interface. Você não precisa saber que o objeto é, por exemplo, uma Lista, um Dicionário, uma LinkedList, uma OrderedList ou qualquer outra coisa. Como você sabe que todos esses são IEnumerables, você pode usar os métodos de IEnumerable para percorrer cada elemento dessas coleções, um de cada vez. Você não precisa saber que uma classe de saída é um ConsoleWriter, um FileWriter, um NetworkStreamWriter ou mesmo um MulticastWriter que usa outros tipos de gravadores; tudo o que você precisa saber é que eles são todos IWriters (ou o que for), e, portanto, eles têm um método "Write" no qual você pode passar uma string, e essa string será emitida.

KeithS
fonte
7

Embora seja claramente um prazer para o programador (no começo, pelo menos) ter herança múltipla, essa é uma omissão quase trivial e você (na maioria dos casos) não deve confiar na herança múltipla. As razões para isso são complexas, mas se você realmente quiser aprender sobre isso, considere a experiência das duas linguagens de programação mais famosas (pelo índice TIOBE ) que a suportam: C ++ e Python (3ª e 8ª, respectivamente).

No Python, a herança múltipla é suportada, mas é quase universalmente incompreendida pelos programadores e afirmar que você sabe como funciona, significa ler e entender este artigo sobre o tópico: Ordem de resolução de método . Outra coisa que aconteceu no Python é que as interfaces meio que entraram na linguagem - Zope.Interfaces.

Para C ++, pesquise no Google "hierarquia de diamantes C ++" e veja a feiúra que está prestes a cobri-lo. Os profissionais de C ++ sabem como usar herança múltipla. Todo mundo normalmente está apenas brincando sem saber quais serão os resultados. Outra coisa que mostra o quão úteis são as interfaces é o fato de que, em muitos casos, uma classe pode precisar substituir completamente o comportamento de seus pais. Nesses casos, a implementação pai é desnecessária e sobrecarrega a classe filho apenas com a memória das variáveis ​​privadas do pai, o que pode não ser importante na idade do C #, mas é importante quando você faz a programação incorporada. Se você usa uma interface, esse problema é inexistente.

Em conclusão, as interfaces são, na minha opinião, uma parte essencial do OOP, porque elas impõem um contrato. A herança múltipla é útil em casos limitados, e geralmente apenas para indivíduos que sabem como usá-la. Portanto, se você é iniciante, é quem é tratado pela falta de herança múltipla - isso lhe dá uma chance melhor de não cometer erros .

Além disso, historicamente, a idéia de uma interface está enraizada muito antes das especificações de design em C # da Microsoft. A maioria das pessoas considera o C # uma atualização sobre o Java (na maioria dos sentidos) e adivinha de onde o C # obteve suas interfaces - Java. Protocolo é uma palavra mais antiga para o mesmo conceito e muito mais antiga que .NET.

Atualização: Agora vejo que posso ter respondido a uma pergunta diferente - por que interfaces, em vez de herança múltipla, mas essa parecia a resposta que você estava procurando. Além de que uma linguagem OO deve ter pelo menos uma das duas, e as outras respostas cobriram sua pergunta original.

George Penn.
fonte
6

É difícil para mim imaginar código C # limpo e orientado a objetos sem o uso de interfaces. Você os utiliza sempre que deseja impor a disponibilidade de determinadas funcionalidades sem forçar a herança de classes de uma classe base específica, e isso permite que seu código tenha o nível relevante de acoplamento (baixo).

Não concordo que a herança múltipla seja melhor do que ter interfaces, mesmo antes de começarmos a argumentar que a herança múltipla vem com seu próprio conjunto de dificuldades. As interfaces são uma ferramenta básica para permitir o polimorfismo e a reutilização de código. Do que mais precisamos?

Daniel B
fonte
5

Eu, pessoalmente, amo a classe abstrata e a uso mais do que uma interface. A principal diferença vem da integração com interfaces .NET, como IDisposable, IEnumerable e assim por diante ... e com interoperabilidade COM. Além disso, a interface é um pouco menos esforço para escrever do que uma classe abstrata, e uma classe pode implementar mais de uma interface enquanto só pode herdar de uma classe.

Dito isso, acho que a maioria das coisas para as quais eu usaria uma interface é melhor servida por uma classe abstrata. As funções virtuais puras - funções abstratas - permitem forçar um implementador a definir uma função semelhante à maneira como uma interface obriga um implementador a definir todos os seus membros.

No entanto, você normalmente usa uma interface quando não deseja impor um determinado design à superclasse, enquanto usaria uma classe abstrata para ter um design reutilizável que já é implementado principalmente.

Eu usei interfaces extensivamente com ambientes de plug-in de gravação usando o espaço para nome System.ComponentModel. Eles são bastante úteis.

Jonathan Henson
fonte
1
Muito bem colocado! Acho que você vai gostar do meu artigo sobre aulas abstratas. Abstração é tudo .
Steven Jeuris
5

Eu posso dizer que me relaciono com isso. Quando comecei a aprender sobre OO e C #, também não recebi interfaces. Isso está ok. Só precisamos encontrar algo que faça com que você aprecie as conveniências das interfaces.

Deixe-me tentar duas abordagens. E me perdoe pelas generalizações.

Experimente 1

Digamos que você seja um falante nativo de inglês. Você vai para outro país onde o inglês não é o idioma nativo. Você precisa de ajuda. Você precisa de alguém que possa ajudá-lo.

Você pergunta: "Ei, você nasceu nos Estados Unidos?" Isso é herança.

Ou você pergunta: "Ei, você fala inglês"? Esta é a interface.

Se você se importa com o que faz, pode confiar em interfaces. Se você se importa com o que é, confia na herança.

Não há problema em confiar na herança. Se você precisa de alguém que fala inglês, gosta de chá e gosta de futebol, é melhor pedir um britânico. :)

Experimente 2

Ok, vamos tentar outro exemplo.

Você usa bancos de dados diferentes e precisa implementar classes abstratas para trabalhar com eles. Você passará sua classe para alguma classe do fornecedor do banco de dados.

public abstract class SuperDatabaseHelper
{
   void Connect (string User, string Password)
}

public abstract class HiperDatabaseHelper
{
   void Connect (string Password, string User)
}

Herança múltipla, você diz? Tente isso com o caso acima. Você não pode. O compilador não saberá para qual método Connect você está tentando chamar.

interface ISuperDatabaseHelper
{
  void Connect (string User, string Password)
}

interface IHiperDatabaseHelper
{
   void Connect (string Password, string User)
}

Agora, há algo com que podemos trabalhar - pelo menos em C # - onde podemos implementar interfaces explicitamente.

public class MyDatabaseHelper : ISuperDatabaseHelper, IHiperDatabaseHelper
{
   IHiperDataBaseHelper.Connect(string Password, string User)
   {
      //
   }

   ISuperDataBaseHelper.Connect(string User, string Password)
   {
      //
   }

}

Conclusão

Os exemplos não são os melhores, mas acho que isso é válido.

Você só "obterá" interfaces quando sentir necessidade delas. Até eles, você pensará que não é para você.

Luiz Angelo
fonte
A primeira tentativa é o que deu o meu voto.
Osundblad
1
Estou usando totalmente a analogia entre americano e inglês a partir de agora. Isso é fantastico.
Bryan Boettcher
Explicado de uma maneira mais simples! Fantástico.
Aimal Khan
4

Existem 2 razões principais:

  1. Falta de herança múltipla. Você pode herdar de uma classe base e implementar qualquer número de interfaces. Essa é a única maneira de "fazer" herança múltipla no .NET.
  2. Interoperabilidade COM. Qualquer coisa que precise ser usada por tecnologias "mais antigas" precisará ter interfaces definidas.
Tangurena
fonte
O ponto 1 é definitivamente a razão ea razão desenvolvido por desenvolvedores própria Microsoft
Pankaj Upadhyay
1
@Pankja Na verdade, eles adotaram a idéia da interface do Java (como boa parte dos recursos do C #).
Oliver Weiler
3

O uso de interfaces ajuda o sistema a ficar dissociado e, portanto, mais fácil de refatorar, alterar e reimplementar. É um conceito muito central para a ortodoxia orientada a objetos e eu aprendi sobre isso quando os gurus de C ++ criaram "classes abstratas puras" que são bastante equivalentes às interfaces.

Jesse C. Slicer
fonte
A dissociação é importante porque mantém diferentes componentes de um sistema independentes um do outro. Que mesmo alterações de grande impacto em um componente não se propagam para outros componentes. Pense nos plugues de alimentação como uma interface para sua empresa de serviços públicos (especificando a tensão, os pinos físicos e o formato do plugue). Graças a essa interface, o utilitário pode mudar completamente a maneira como produz energia (por exemplo, usar a tecnologia solar), mas nenhum dos dispositivos notará nem muito menos a mudança.
Miraculixx
3

As interfaces por si só não são muito úteis. Porém, quando implementado por classes concretas, você percebe que ele oferece a flexibilidade de ter uma ou mais implementações. O bônus é que o objeto que usa a interface não precisa saber como vão os detalhes da implementação real - isso é chamado de encapsulamento.

Ronald
fonte
2

Eles são usados ​​principalmente para reutilização de código. Se você codifica para a interface, pode usar uma classe diferente que herda dessa interface e não quebra tudo.

Além disso, eles são muito úteis em serviços da web onde você deseja que o cliente saiba o que uma classe faz (para que eles possam consumi-la), mas não deseja fornecer o código real.

Tom Squires
fonte
2

Como um jovem programador / desenvolvedor, apenas aprendendo C #, talvez você não veja a utilidade da interface, porque você pode escrever seus códigos usando suas classes e o código funciona bem, mas no cenário da vida real, criar um aplicativo escalável, robusto e sustentável envolve o uso de algumas arquiteturas e padrões, que só podem ser possíveis usando a interface, por exemplo, na injeção de dependência.

Adewole Ayobami
fonte
1

Uma implementação no mundo real:

Você pode converter um objeto como o tipo de interface:

IHelper h = (IHelper)o;
h.HelperMethod();

Você pode criar uma lista de uma interface

List<IHelper> HelperList = new List<IHelper>();

Com esses objetos, você pode acessar qualquer um dos métodos ou propriedades da interface. Dessa maneira, você pode definir uma interface para sua parte de um programa. E construa a lógica ao seu redor. Em seguida, outra pessoa pode implementar sua interface nos objetos de negócios. Se o BO mudar, ele poderá alterar a lógica dos componentes da interface e não exigir uma alteração na lógica da sua peça.

SoylentGray
fonte
0

As interfaces emprestam à modularidade no estilo de plug-in, fornecendo um mecanismo para as classes entenderem (e se inscreverem) em certos tipos de mensagens que seu sistema entrega. Eu vou elaborar.

No seu aplicativo, você decide que sempre que um formulário for carregado ou recarregado, você deseja que todas as coisas que ele hospede sejam limpas. Você define uma IClearinterface que implementa Clear. Além disso, você decide que sempre que o usuário pressionar o botão Salvar, o formulário deve tentar manter seu estado. Assim, tudo o que obedece ISaverecebe uma mensagem para persistir seu estado. Obviamente, na maioria das vezes, a maioria das interfaces manipula várias mensagens.

O que diferencia as interfaces é que o comportamento comum pode ser alcançado sem herança. A classe que implementa uma determinada interface simplesmente entende como se comportar quando emitido um comando (uma mensagem de comando) ou como responder quando consultada (uma mensagem de consulta). Essencialmente, as classes em seu aplicativo compreendem as mensagens que ele fornece. Isso facilita a construção de um sistema modular no qual as coisas podem ser conectadas.

Na maioria dos idiomas, existem mecanismos (como o LINQ ) para consultar itens que respeitam uma interface. Isso geralmente ajudará a eliminar a lógica condicional, porque você não precisará dizer coisas diferentes (que não são necessárias derivadas da mesma cadeia de herança) como se comportar de maneira semelhante (de acordo com uma mensagem específica). Em vez disso, você reúne tudo o que entende uma determinada mensagem (obedece a uma interface) e publica a mensagem.

Por exemplo, você pode substituir ...

Me.PublishDate.Clear()
Me.Subject.Clear()
Me.Body.Clear()

...com:

For Each ctl As IClear In Me.Controls.OfType(Of IClear)()
    ctl.Clear()
Next

O que efetivamente soa muito como:

Ouçam, ouçam! Todo mundo que entende de limpeza, por favor Clearagora!

Dessa forma, podemos evitar programaticamente dizer a cada uma das coisas para se limpar. E quando itens passíveis de limpeza são adicionados no futuro, eles simplesmente respondem sem nenhum código adicional.

Mario T. Lanza
fonte
0

O seguinte é pseudocódigo:

class MyClass{

    private MyInterface = new MyInterfaceImplementationB();

    // Code using Thingy 

}

interface MyInterface{

    myMethod();

}

class MyInterfaceImplementationA{ myMethod(){ // method implementation A } }

class MyInterfaceImplementationB{ myMethod(){ // method implementation B } }

class MyInterfaceImplementationC{ myMethod(){ // method implementation C } }

As últimas classes podem ser implementações completamente diferentes.

A menos que a herança múltipla seja possível, a herança impõe a implementação da classe pai, tornando as coisas mais rígidas. A programação em interfaces, por outro lado, pode permitir que seu código ou uma estrutura seja extremamente flexível. Se você encontrar um caso em que deseja trocar de classe em uma cadeia de herança, entenderá o porquê.

Por exemplo, uma estrutura que fornece um Reader originalmente destinado a ler dados do disco pode ser reimplementada para fazer algo da mesma natureza, mas de uma maneira totalmente diferente. Como interpretar o código Morse, por exemplo.

James Poulson
fonte