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?
fonte
Respostas:
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.
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.
fonte
Assume
chamadas, 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.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.
fonte
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.
fonte
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.
fonte
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.
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.
fonte
Você provavelmente já usou
foreach
e 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.
fonte
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
new
palavra - 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.
fonte
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.
fonte
É 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?
fonte
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.
fonte
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.
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.
Agora, há algo com que podemos trabalhar - pelo menos em C # - onde podemos implementar interfaces explicitamente.
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ê.
fonte
Existem 2 razões principais:
fonte
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.
fonte
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.
fonte
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.
fonte
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.
fonte
Uma implementação no mundo real:
Você pode converter um objeto como o tipo de interface:
Você pode criar uma lista de uma interface
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.
fonte
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
IClear
interface que implementaClear
. 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 obedeceISave
recebe 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 ...
...com:
O que efetivamente soa muito como:
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.
fonte
O seguinte é pseudocódigo:
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.
fonte