Estou em um ponto do aprendizado de desenvolvimento em que sinto que devo aprender mais sobre interfaces.
Eu frequentemente leio sobre eles, mas parece que não consigo entendê-los.
Eu li exemplos como: Classe base animal, com interface IAnimal para coisas como 'Walk', 'Run', 'GetLegs', etc. - mas nunca trabalhei em algo e senti como "Ei, eu devo usar uma interface aqui!"
o que estou perdendo? Por que é um conceito tão difícil para eu entender! Estou apenas intimidado pelo fato de nunca ter percebido uma necessidade concreta de uma - principalmente devido a algum aspecto ausente de compreendê-las! Isso me faz sentir como se estivesse perdendo algo no topo em termos de ser um desenvolvedor! Se alguém teve uma experiência como essa e teve um avanço, eu apreciaria algumas dicas sobre como entender esse conceito. Obrigado.
fonte
Respostas:
resolve este problema concreto:
você tem a, b, c, d de 4 tipos diferentes. em todo o seu código, você tem algo como:
por que eles não implementam IProcessable e, em seguida,
isso aumentará muito quando você adicionar, digamos, 50 tipos de classes que todos fazem a mesma coisa.
Outro problema concreto:
Você já deu uma olhada no System.Linq.Enumerable? Ele define vários métodos de extensão que operam em qualquer tipo que implemente IEnumerable. Como qualquer coisa que implemente o IEnumerable basicamente diz "Suporte a iteração em um padrão não ordenado de tipo foreach", você pode definir comportamentos complexos (Contagem, Máx, Onde, Selecionar etc.) para qualquer tipo enumerável.
fonte
foreach(IMyCompanyWidgetFrobber a in list) a.Frob(widget, context);
Gosto muito da resposta de Jimmy, mas sinto que preciso acrescentar algo a ela. A chave para tudo isso é o "capaz" no IProcess capaz. Indica uma capacidade (ou propriedade, mas significa "qualidade intrínseca", não no sentido de propriedades C #) do objeto que implementa a interface. O IAnimal provavelmente não é um bom exemplo para uma interface, mas o IWalkable pode ser uma boa interface se o seu sistema tiver muitas coisas que podem ser executadas. Você pode ter aulas derivadas de Animal, como Cão, Vaca, Peixe, Cobra. Os dois primeiros provavelmente implementariam o IWalkable, os dois últimos não andam, portanto não. Agora você pergunta "por que não apenas ter outra superclasse, WalkingAnimal, da qual derivam cão e vaca?". A resposta é quando você tem algo completamente fora da árvore de herança que também pode andar, como um robô. O robô implementaria o IWalkable, mas provavelmente não derivaria do Animal. Se você quiser uma lista de coisas que podem andar,
Agora substitua o IWalkable por algo mais semelhante ao software IPersistable, e a analogia fica muito mais próxima do que você veria em um programa real.
fonte
Use interfaces quando implementações da mesma funcionalidade diferirem.
Use classes abstratas / base quando precisar compartilhar uma implementação concreta comum.
fonte
is
palavra - chave)Pense em uma interface como um contrato. É uma maneira de dizer: "Essas classes devem seguir esse conjunto de regras".
Portanto, no exemplo IAnimal, é uma maneira de dizer: "DEVO poder chamar Executar, Caminhar etc. nas classes que implementam IAnimal".
Por que isso é útil? Você pode criar uma função que se baseie no fato de que deve poder chamar Executar e Andar, por exemplo, no objeto. Você pode ter o seguinte:
... e repita isso para todos os objetos que você sabe que podem correr e andar. No entanto, com sua interface IAnimal, você pode definir a função uma vez da seguinte maneira:
Ao programar na interface, você confia essencialmente nas classes para implementar a intenção da interface. Portanto, em nosso exemplo, o pensamento é: "Eu não ligo para como eles correm e andam, desde que corram e andem. Meu RunThenWalk será válido desde que cumpram esse contrato. Funciona perfeitamente bem sem saber mais nada sobre a classe."
Há também uma boa discussão nesta questão relacionada .
fonte
Não se preocupe tanto. Muitos desenvolvedores raramente precisarão escrever uma interface. Você freqüentemente usará interfaces disponíveis na estrutura .NET , mas se não sentir necessidade de escrever uma tão cedo, não há nada de surpreendente nisso.
O exemplo que eu sempre dou a alguém é se você tem uma aula de Veleiro e uma aula de Viper. Eles herdam a classe Boat e a classe Car, respectivamente. Agora diga que você precisa percorrer todos esses objetos e chamar o
Drive()
método deles . Enquanto você pode escrever um código como o seguinte:Seria muito mais simples escrever:
fonte
Jimmy está certo quando você deseja usar uma única variável para vários tipos, mas todos eles implementam o mesmo método por meio de uma declaração de interface. Então você pode chamá-los de método principal na variável digitada na interface.
Há uma segunda razão para usar interfaces, no entanto. Quando o arquiteto do projeto é uma pessoa diferente do codificador de implementação, ou existem vários codificadores de implementação e um gerente de projeto. O responsável pode escrever um monte de interfaces e verificar se o sistema interopera e deixar que os desenvolvedores preencham as interfaces com as classes de implementação. Essa é a melhor maneira de garantir que várias pessoas escrevam classes compatíveis e possam fazê-lo em paralelo.
fonte
Eu gosto da analogia do exército.
O sargento não se importa se você é desenvolvedor de software , músico ou advogado .
Você é tratado como soldado .
É mais fácil para o sargento não se incomodar com detalhes específicos de pessoas com quem ele está trabalhando,
tratar todos como abstrações de soldados (... e puni-los quando eles falham em agir como aqueles).
A capacidade de as pessoas agirem como soldados é chamada polimorfismo.
Interfaces são construções de software que ajudam a alcançar o polimorfismo.
A necessidade de abstrair os detalhes para obter simplicidade é a resposta à sua pergunta.
fonte
Na minha experiência, a força motriz para criar interfaces não ocorreu até eu começar a fazer testes de unidade com uma estrutura de simulação. Ficou bastante claro que o uso de interfaces tornaria a zombaria muito mais fácil (já que a estrutura dependia dos métodos serem virtuais). Quando comecei, vi o valor de abstrair a interface da minha classe da implementação. Mesmo se eu não criar uma interface real, tento agora tornar meus métodos virtuais (fornecendo uma interface implícita que pode ser substituída).
Existem muitas outras razões que eu descobri para reforçar a boa prática de refatoração para interfaces, mas o teste de unidade / zombaria foi o que proporcionou o "momento aha" inicial da experiência prática.
EDIT : Para esclarecer, com testes de unidade e zombaria, sempre tenho duas implementações - a implementação real e concreta e uma implementação de simulação alternativa usada nos testes. Depois de ter duas implementações, o valor da interface se torna óbvio - lide com ela em termos da interface para que você possa substituir a implementação a qualquer momento. Neste caso, estou substituindo-o por uma interface simulada. Eu sei que posso fazer isso sem uma interface real se minha classe for construída corretamente, mas o uso de uma interface real reforça isso e a torna mais limpa (mais clara para o leitor). Sem esse ímpeto, acho que não teria apreciado o valor das interfaces, já que a maioria das minhas classes apenas possui uma implementação concreta.
fonte
Alguns exemplos de não programação que podem ajudá-lo a ver os usos apropriados das interfaces na programação.
Existe uma interface entre dispositivos elétricos e a rede elétrica - é o conjunto de convenções sobre o formato dos plugues e soquetes e as tensões / correntes entre eles. Se você deseja implementar um novo dispositivo elétrico, desde que o plugue siga as regras, ele poderá obter serviços da rede. Isso torna a extensibilidade muito fácil e remove ou reduz os custos de coordenação : você não precisa notificar o fornecedor de energia elétrica sobre como o seu novo dispositivo funciona e chegar a um acordo em separado sobre como conectar seu novo dispositivo à rede.
Os países possuem bitolas ferroviárias padrão. Isso permite uma divisão do trabalho entre empresas de engenharia que instalam trilhos e empresas de engenharia que constroem trens para rodar nesses trilhos, e possibilita que as empresas ferroviárias substituam e atualizem trens sem reprojetar o sistema inteiro.
O serviço que uma empresa apresenta a um cliente pode ser descrito como uma interface: uma interface bem definida enfatiza o serviço e oculta os meios . Quando você coloca uma carta em uma caixa de correio, espera que o sistema postal entregue a carta dentro de um determinado período, mas não tem expectativas sobre como a carta é entregue: você não precisa saber e o serviço postal tem a flexibilidade de escolha o meio de entrega que melhor atenda aos requisitos e às circunstâncias atuais. Uma exceção a isso é a capacidade dos clientes de escolher o correio aéreo - esse não é o tipo de interface que um programador de computador moderno teria projetado, pois revela muito da implementação.
Exemplos da natureza: não gosto muito de exemplos de como comer (), makesSound (), movimentos (), etc. Eles descrevem o comportamento, o que é correto, mas não descrevem interações e como são ativadas . Os exemplos óbvios de interfaces que permitem interações na natureza estão relacionados à reprodução; por exemplo, uma flor fornece uma certa interface para uma abelha, para que a polinização possa ocorrer.
fonte
É inteiramente possível passar a vida inteira como desenvolvedor .net e nunca escrever suas próprias interfaces. Afinal, nós sobrevivemos bem sem eles por décadas e nossos idiomas ainda estavam completos em Turing.
Não sei por que você precisa de interfaces, mas posso fornecer uma lista de onde as usamos em nosso projeto atual:
Em nosso modelo de plug-in, carregamos plug-ins por interface e fornecemos essa interface para que os gravadores de plug-in estejam em conformidade.
Em nosso sistema de mensagens entre máquinas, todas as classes de mensagens implementam uma interface específica e são "desembrulhadas" usando a interface.
Nosso sistema de gerenciamento de configurações define uma interface usada para definir e recuperar as configurações.
Temos uma interface que usamos para evitar um problema desagradável de referência circular. (Não faça isso se não for necessário.)
Eu acho que se existe uma regra, é usar interfaces quando você deseja agrupar várias classes dentro de um relacionamento é-um, mas você não deseja fornecer nenhuma implementação na classe base.
fonte
Um exemplo de código (combinação de Andrew com um extra meu em qual é o objetivo das interfaces ), que também mostra o porquê da interface, em vez de uma classe abstrata em linguagens sem suporte para herança múltipla (c # e Java):
Observe que o FileLogger e o DataBaseLogger não precisam da interface (pode ser uma classe base abstrata do Logger). Mas considere que você é obrigado a usar um criador de logs de terceiros que o força a usar uma classe base (digamos que exponha métodos protegidos que você precisa usar). Como o idioma não suporta herança múltipla, você não poderá usar a abordagem de classe base abstrata.
Resumindo: use uma interface sempre que possível para obter flexibilidade extra em seu código. Sua implementação está menos vinculada, portanto, acomoda melhor para a mudança.
fonte
Usei interfaces de vez em quando e aqui está o meu uso mais recente (os nomes foram generalizados):
Eu tenho vários controles personalizados em um WinForm que precisam salvar dados no meu objeto de negócios. Uma abordagem é chamar cada controle separadamente:
O problema com esta implementação é que sempre que adiciono um controle, tenho que entrar no meu método "Salvar dados" e adicionar o novo controle.
Alterei meus controles para implementar uma interface ISaveable que possui o método SaveToBusinessObject (...), agora meu método "Save Data" apenas repete os controles e, se encontrar um que é ISaveable, chama SaveToBusinessObject. Portanto, agora, quando um novo controle é necessário, tudo o que alguém precisa fazer é implementar o ISaveable nesse objeto (e nunca tocar em outra classe).
O benefício muitas vezes não realizado para as interfaces é que você localiza as modificações. Uma vez definido, você raramente alterará o fluxo geral de um aplicativo, mas frequentemente fará alterações no nível de detalhe. Quando você mantém os detalhes em objetos específicos, uma alteração no ProcessA não afetará uma alteração no ProcessB. (As classes base também oferecem esse benefício.)
EDIT: Outro benefício é a especificidade das ações. Como no meu exemplo, tudo o que quero fazer é salvar os dados; Não me importo com o tipo de controle ou se ele pode fazer outra coisa - só quero saber se posso salvar os dados no controle. Isso deixa meu código salvo bem claro - não há verificações para ver se é texto, numérico, booleano ou qualquer outra coisa, porque o controle personalizado lida com tudo isso.
fonte
Você deve definir uma interface assim que forçar um comportamento para sua classe.
O comportamento de um animal pode envolver caminhar, comer, correr etc. Portanto, você os define como interfaces.
Outro exemplo prático é a interface ActionListener (ou Runnable). Você os implementaria quando precisar acompanhar um evento específico. Portanto, você precisa fornecer a implementação para o
actionPerformed(Event e)
método em sua classe (ou subclasse). Da mesma forma, para a interface Runnable, você fornece a implementação dopublic void run()
método.Além disso, você pode ter essas interfaces implementadas por qualquer número de classes.
Outra instância em que as interfaces são usadas (em Java) é implementar a herança múltipla oferecida em C ++.
fonte
Suponha que você queira modelar aborrecimentos que podem acontecer quando você tenta dormir.
Modelar antes das interfaces
Como você vê claramente muitas coisas podem ser irritantes quando você tenta dormir.
Uso de classes sem interfaces
Mas quando se trata de usar essas classes, temos um problema. Eles não têm nada em comum. Você precisa chamar cada método separadamente.
Modelo com interfaces
Para superar esse problema, podemos introduzir uma iterface
E implementá-lo dentro de classes
Uso com interfaces
O que tornará o uso dessas classes muito mais fácil
fonte
Neighbour
eLampJustOutsideYourWindow
também tem que implementarAnnoying
?O exemplo mais fácil de se dar é algo como Processadores de pagamento (Paypal, PDS etc.).
Digamos que você crie uma interface IPaymentProcessor que possua os métodos ProcessACH e ProcessCreditCard.
Agora você pode implementar uma implementação concreta do Paypal. Fazer esses métodos chamarem funções específicas do PayPal.
Se você decidir mais tarde precisar mudar para outro provedor, poderá. Basta criar outra implementação concreta para o novo provedor. Como tudo o que você está vinculado é a sua interface (contrato), é possível trocar qual deles seu aplicativo usa sem alterar o código que o consome.
fonte
Também permite realizar testes de unidade Mock (.Net). Se sua classe usa uma interface, você pode simular o objeto em seus testes de unidade e facilmente testar a lógica (sem atingir o banco de dados, o serviço da web, etc.).
http://www.nmock.org/
fonte
Se você procurar os assemblies do .NET Framework e detalhar as classes base para qualquer um dos objetos padrão, notará muitas interfaces (membros nomeados como ISomeName).
As interfaces são basicamente para implementar estruturas, grandes ou pequenas. Eu me senti da mesma maneira com relação às interfaces até querer escrever uma estrutura própria. Também descobri que entender interfaces me ajudou a aprender estruturas muito mais rapidamente. No momento em que você deseja escrever uma solução mais elegante para praticamente qualquer coisa, verá que uma interface faz muito sentido. É como um método de deixar uma classe vestir as roupas apropriadas para o trabalho. Mais importante, as interfaces permitem que os sistemas se tornem muito mais auto-documentados, porque objetos complexos se tornam menos complexos quando a classe implementa interfaces, o que ajuda a categorizar sua funcionalidade.
As classes implementam interfaces quando desejam poder participar de uma estrutura explícita ou implicitamente. Por exemplo, IDisposable é uma interface comum que fornece assinatura de método para o método Dispose () popular e útil. Em uma estrutura, tudo o que você ou outro desenvolvedor precisa saber sobre uma classe é que, se ela implementar IDisposable, você saberá que ((IDisposable) myObject) .Dispose () estará disponível para ser chamado para fins de limpeza.
EXEMPLO CLÁSSICO: sem implementar a interface IDisposable, você não pode usar a construção de palavra-chave "using ()" em C #, porque exige que qualquer objeto especificado como parâmetro possa ser implicitamente convertido em IDisposable.
EXEMPLO COMPLEXO: Um exemplo mais complexo seria a classe System.ComponentModel.Component. Esta classe implementa IDisposable e IComponent. A maioria dos objetos .NET, se não todos, que possuem um designer visual associado a eles, implementa o IComponent para que o IDE possa interagir com o componente.
CONCLUSÃO: À medida que você se familiariza com o .NET Framework, a primeira coisa que você fará quando encontrar uma nova classe no Pesquisador de objetos ou na ferramenta .NET Reflector (gratuita) ( http://www.red-gate.com / products / reflector / ) é para verificar de qual classe ele herda e também as interfaces que ele implementa. O .NET Reflector é ainda melhor que o Pesquisador de objetos, pois também permite ver as classes derivadas. Isso permite que você aprenda sobre todos os objetos que derivam de uma classe específica, potencialmente aprendendo sobre a funcionalidade da estrutura que você não sabia que existia. Isso é particularmente significativo quando os namespaces atualizados ou novos são adicionados ao .NET Framework.
fonte
Considere que você está fazendo um jogo de tiro em primeira pessoa. O jogador tem várias armas para escolher.
Podemos ter uma interface
Gun
que define uma funçãoshoot()
.Precisamos de diferentes subclasses de
Gun
classe, a saber,ShotGun
Sniper
e assim por diante.Classe de atirador
O atirador tem todas as armas em sua armadura. Vamos criar um
List
para representá-lo.O atirador percorre suas armas, como e quando necessário, usando a função
switchGun()
Podemos definir a arma atual, usando a função acima e simplesmente chamar a
shoot()
função, quandofire()
for chamada.O comportamento da função de disparo varia de acordo com diferentes implementações da
Gun
interface.Conclusão
Crie uma interface, quando uma função de classe depende de uma função de outra classe , que está sujeita a alterar seu comportamento, com base na instância (objeto) da classe implementada.
por exemplo, a
fire()
função daShooter
classe espera que as armas (Sniper
,ShotGun
) implementem ashoot()
função. Então, se trocarmos a arma e disparar.Nós mudamos o comportamento da
fire()
função.fonte
Expandir o que Larsenal disse. Uma interface é um contrato que todas as classes de implementação devem seguir. Por esse motivo, você pode usar uma técnica chamada programação para o contrato. Isso permite que seu software se torne independente da implementação.
fonte
As interfaces geralmente são usadas quando você deseja definir um comportamento que os objetos possam exibir.
Um bom exemplo disso no mundo .NET é a interface IDisposable , usada em todas as classes da Microsoft que usam recursos do sistema que devem ser liberados manualmente. Requer que a classe que o implementa tenha um método Dispose ().
(O método Dispose () também é chamado pela construção de linguagem using para VB.NET e C # , que funciona apenas em
IDisposable
s)Lembre-se de que você pode verificar se um objeto implementa uma interface específica usando construções como
TypeOf ... Is
(VB.NET),is
(C #),instanceof
(Java), etc.fonte
Como várias pessoas provavelmente já responderam, as interfaces podem ser usadas para impor certos comportamentos entre classes que não os implementarão da mesma maneira. Portanto, ao implementar uma interface, você está dizendo que sua classe tem o comportamento da interface. A interface IAnimal não seria uma interface típica porque as classes Dog, Cat, Bird etc. são tipos de animais e provavelmente devem estendê-la, que é um caso de herança. Em vez disso, nesse caso, uma interface seria mais parecida com o comportamento animal, como IRunnable, IFlyable, ITrainable etc.
As interfaces são boas para muitas coisas, uma das principais coisas é a conectabilidade. Por exemplo, declarar um método que possui um parâmetro List permitirá que qualquer coisa que implemente a interface List seja transmitida, permitindo que o desenvolvedor remova e conecte uma lista diferente posteriormente, sem precisar reescrever uma tonelada de código.
É possível que você nunca use interfaces, mas se estiver criando um projeto do zero, especialmente uma estrutura de algum tipo, provavelmente desejará se familiarizar com elas.
Eu recomendaria a leitura do capítulo sobre interfaces em Java Design, de Coad, Mayfield e Kern. Eles explicam um pouco melhor do que o texto introdutório médio. Se você não usa Java, basta ler o início do capítulo, que é basicamente conceitos.
fonte
Como qualquer técnica de programação que adiciona flexibilidade ao seu sistema, as interfaces também adicionam algum nível de complexidade. Eles geralmente são ótimos e você pode usá-lo em qualquer lugar (você pode criar uma interface para todas as suas classes) - mas, ao fazê-lo, você criaria um sistema mais complexo que seria mais difícil de manter.
Há uma troca aqui, como de costume: flexibilidade sobre manutenção. Qual deles é mais importante ? Não há respostas - isso depende do projeto. Mas lembre-se de que todos os softwares precisarão ser mantidos ...
Portanto, meu conselho: não use interfaces até que você realmente precise delas. (Com o Visual Studio, você pode extrair uma interface de uma classe existente em 2 segundos - portanto, não se apresse.)
Dito isto, quando você precisa criar uma interface?
Faço isso quando refatorando um método que de repente precisa processar duas ou mais classes semelhantes. Em seguida, crio uma interface, atribuo essa interface às duas (ou mais) classes semelhantes e altero o tipo de parâmetro do método (substitua o tipo de classe pelo tipo de interface).
E funciona: o)
Uma exceção: quando zombar de objetos, a interface é muito mais fácil de usar. Então, eu costumo criar interface apenas para isso.
PS: quando escrevo "interface", quero dizer: "interface de qualquer classe base", incluindo classes de interface pura. Observe que as classes abstratas geralmente são uma aposta melhor do que as interfaces puras, pois você pode adicionar lógica a elas.
Atenciosamente, Sylvain.
fonte
As interfaces ficarão evidentes quando você se tornar um desenvolvedor de bibliotecas (alguém que codifica para outros codificadores). A maioria de nós começa como desenvolvedores de aplicativos , onde usamos APIs e bibliotecas de programação existentes.
Na mesma linha que as interfaces são um contrato , ninguém mencionou ainda que as interfaces são uma ótima maneira de tornar algumas partes do seu código estáveis . Isso é especialmente útil quando se trata de um projeto de equipe (ou quando você está desenvolvendo código usado por outros desenvolvedores). Então, aqui está um cenário concreto para você:
Consulte também esta pergunta relacionada sobre a codificação para uma interface .
fonte
Existem muitos propósitos para usar uma interface.
Use no comportamento polimórfico. Onde você deseja chamar métodos específicos de uma classe filho com uma interface tendo uma referência à classe filho.
Ter um contrato com as classes para implementar todos os métodos onde for necessário, como o uso mais comum, é com objetos COM, onde uma classe de wrapper é gerada em uma DLL que herda a interface; esses métodos são chamados nos bastidores e você só precisa implementá-los, mas com a mesma estrutura definida na DLL COM, que você só pode conhecer através da interface que eles expõem.
Reduzir o uso de memória carregando métodos específicos em uma classe. Como se você tivesse três objetos de negócios e eles fossem implementados em uma única classe, você pode usar três interfaces.
Por exemplo, IUser, IOrder, IOrderItem
Se você deseja adicionar apenas um usuário, faça o seguinte:
fonte