Interface x Clase abstrata

Olá. Antes que me ataquem por ser um tópico muitíssimo duplicado, quero explicar minha dúvida.
Conheço bem a diferença técnica entre uma Interface e uma classe abstrata, porém nesse momento parei para pensar e vi que eu não sei explicar o porque de usar uma Interface ao invés de uma classe abstrata. As duas possuem recursos diferentes, porém eu posso muito bem fazer o trabalho de uma Interface em uma classe abstrata. Daí vai a minha dúvida, porque foi criada a Interface? Já vi gente que diz que foi para resolver o problema de múltipla herança, mas creio que ainda há uma resposta mais sensata.
Valeu :smiley:

Talvez o link abaixo possa lhe ajudar.

Então você não conhece bem a diferença entre uma e outra.
Pense no seguinte caso:
Eu tenho duas implementações da interface A, AB e AC.
A possui 10 métodos mapeados, que serão implementados por AB e AC, que não tem relação de herança entre eles, tampouco de agregação ou composição.
Acontece que alguns métodos implementados por AB e AC terão a mesma funcionalidade.
Por estarmos usando uma interface, somos obrigados a implementar a mesma lógica dentro dos métodos idênticos em AB e AC.

Agora, se usássemos uma classe abstrata B para implementar A e estendessemos AB e AC de B, teríamos a possibilidade de implementar em B os métodos iguais e em AB e AC os métodos específicos.

Sacou?

Bom dia amigo, realmente existem diferenças entre classes abstratas e interfaces, entre elas classe abstrata pode ter metodos implementados, interface não, uma interface pode ser instanciada apesar de nunca ser, uma classe abastrata só pode ser herdada, o problema é que o conceito de herança fere o encapsulamento fazendo com que as classes especializadas conhecam muito bem as super classes ou classes mais genericas, agora vamos a um exemplo simples, você tem uma classe funcionario que tem um metodo de autenticação em um sistema interno da empresa, ae você tem um gerente que herda de funcionario, até porque um gerente também é um funcionario, porem ambos tem previlegios diferentes, simples é só sobreescrever o método autentica, até ae a herança serviu muito bem, porem digamos que esse sistema é um site de consultas e você tem clientes que também se autenticam no sistema, e você concorda que um cliente não é um funcionário e se herdassemos as caracteristicas do mesmo iriamos conhecer de mais seus atributos e ferir o encapsulamento, enão podemos usar a interface que tenha um método autentica e que tanto funcionario, gerente e cliente implementa esse método de maneira diferente, ou seja, uma interface faz com que seja possivel o uso de polimorfismo mesmo em classes que não tem nenhum vinculo de herança, porem ambas irão implementar o mesmo comportamento de formas diferentes, espero ter ajudado.

t+

Em um post eu falei um pouco sobre isso. É exatamente a ideia conceitual que o drsmachado apresentou, porém se quiser um exemplo mais prático, talvez para dar uma clarificada melhor, dê uma lida :slight_smile: Sei que o exemplo não trata de classes abstratas, mas a ideia é a mesma.

No Java effective tem tudo sobre isso e muitos outras duvidas…- http://fernandofranzini.wordpress.com/2012/08/07/java-efetivo-aprenda-realmente-a-programar-java/

[quote=RafaelCassau]Bom dia amigo, realmente existem diferenças entre classes abstratas e interfaces, entre elas classe abstrata pode ter metodos implementados, interface não, uma interface pode ser instanciada apesar de nunca ser, uma classe abastrata só pode ser herdada, o problema é que o conceito de herança fere o encapsulamento fazendo com que as classes especializadas conhecam muito bem as super classes ou classes mais genericas, agora vamos a um exemplo simples, você tem uma classe funcionario que tem um metodo de autenticação em um sistema interno da empresa, ae você tem um gerente que herda de funcionario, até porque um gerente também é um funcionario, porem ambos tem previlegios diferentes, simples é só sobreescrever o método autentica, até ae a herança serviu muito bem, porem digamos que esse sistema é um site de consultas e você tem clientes que também se autenticam no sistema, e você concorda que um cliente não é um funcionário e se herdassemos as caracteristicas do mesmo iriamos conhecer de mais seus atributos e ferir o encapsulamento, enão podemos usar a interface que tenha um método autentica e que tanto funcionario, gerente e cliente implementa esse método de maneira diferente, ou seja, uma interface faz com que seja possivel o uso de polimorfismo mesmo em classes que não tem nenhum vinculo de herança, porem ambas irão implementar o mesmo comportamento de formas diferentes, espero ter ajudado.

t+[/quote]

só discordei do “uma interface pode ser instanciada”.

a classe anonima não pode passar desapercebida.

qdo eu tava nessa caminhada de entender o uso de intefaces, eu sempre procurava um exemplo q demonstrasse com clareza, q se resolveria com interface e não se resolveria com class abstrata.

no seu exemplo mesmo poderia ter uma classe:

Autenticavel

e q tanto Funcionario qto Clientes herdavam dela.

então eu continuava achando q não houve necessidade da interface.

até q um dia descobri q Funcionario e Cliente ja herdavam de Pessoa.
e Pessoa não poderia herdar de Autenticavel pq nem td Pessoa era Autenticavel

Oi,

Uma interface deve ser criada se existir ao menos um fator comum entre duas ou mais classes.

Tchauzin!

Você gosta de exemplos relacionados a carros?
Pense na interface como sendo uma especificação, do tipo “automóvel de passageiros” e na classe abstrata como “plataforma Polo”.
Como você deve saber, vocâ não pode comprar uma “plataforma Polo” em uma concessionária da Volkswagen (a “plataforma Polo” seria uma classe abstrata, já que ela implementa várias características comuns mas não implementa todas), mas pode comprar um Gol, um Polo ou um Fox (que são construídos sobre a “plataforma Polo”). Gol, Polo e Fox seriam classes concretas, e um automóvel Gol, Polo ou Fox seria uma instância (um objeto) de cada uma dessas classes concretas.
Quando você vai comprar um carro, você quer apenas um “automóvel de passageiros” (algo que tenha determinadas funcionalidades, que podem ser implementadas de diferentes maneiras por diferentes fabricantes), portanto você está interessado apenas na interface.

Boa tarde GilsonNunes, realmente a interface não é instanciada, eu errei na minha colocação, quiz dizer que é possivel refazer uma implementação default de uma interface por exemplo List, Map, etc, referente ao exemplo da autenticavel, como o JAVA não permite herança multipla seria impossivel por exemplo um gerente ser funcionario e também autenticavel, por isso falamos que o gerente é um funcionário e o mesmo implementa o comportamento autenticavel certo? E só para constar mesmo que você faça com que um gerente herde de autenticavel isso feririria o encapsulamento pois o gerente precisaria conhecer muito sobre autenticavel, o intuito do meu exemplo foi justificar que com uma interface um contrato é estabelecido, já com uma classe abstrata comportamentos são herdados dentre eles varios comportamentos indevidos que deverão ser reemplementados.

[quote=pedroe]Olá. Antes que me ataquem por ser um tópico muitíssimo duplicado, quero explicar minha dúvida.
Conheço bem a diferença técnica entre uma Interface e uma classe abstrata, porém nesse momento parei para pensar e vi que eu não sei explicar o porque de usar uma Interface ao invés de uma classe abstrata. As duas possuem recursos diferentes, porém eu posso muito bem fazer o trabalho de uma Interface em uma classe abstrata. Daí vai a minha dúvida, porque foi criada a Interface? Já vi gente que diz que foi para resolver o problema de múltipla herança, mas creio que ainda há uma resposta mais sensata.
[/quote]

A diferença entre interface e class abstrata não é de implementação. Não é sobre se uma permite herança multipla ou se uma não precisa de implementação. Essa não é a diferença.

A diferença de prende com duas dimensões : identidade e comportamento.

Uma classe abstrata fixa uma identidade. Calendar é uma classe abstrata. O que é Calendar não pode ser nenhuma outra coisa. Isto não é porque o java não permite herança multipla. Isto e´assim conceptualmente, em OO independenmente da tecnologia.
Só que além de um identidade uma classe abstrata pode também fixar um comportamento (que é o caso de Calendar). Todas as filhas da classe abstrata X não apenas são X como se comportam da mesma forma que X e essa forma é ditada por X. Este fixar é opcional,porque eu posso querer apenas fixar a identidade.

Um interface não fixa a identidade mas fixa o comportamento ( o contrato) contudo não fixa como o comportamento é atingido.
Ou seja, se Y é uma interface, todas as implementações de Y podem ser coisas diferentes de Y, mas comportam-se como Y , mas de uma forma que não é ditada por Y.
List é um interface que estabelece um contrato (um comportamento) mas dita como esse comportamento tem que ser implementado. Por isso ha tantas implementações de List.

A diferença maior é poder fixar a identidade. Uma classe fixa uma identidade, uma taxionomia. Uma interface não.
O comportamento sempre é ditado pela interface da mesma forma que a classe abstrata porqu ambas definem contratos.
A interface não pode ditar comportamentos padrão , a class abstrata sim. Estes comportamentos são inerentes ao tipo.

Este ultimo conceito de ditar o comportamento irá alterar-se no java 8 com os métodos default, em que as interfaces podem ditar implementações para os seus métodos, mas mesmo aqui a interface não está ditando (pois ela não consegue proibir o override usando final) está apenas sugerindo como contigência.

O resto é como estes conceitos são traduzidos em java.

Tecnicamente deveriamos falar em contratos em vez de interface pois interface é apenas um construto do java e não necessáriamente um padrão OO. É um tipo possivel. O trait, usado em Scala e outras linguagens, consegue expressar o mesmo que a interface java em termos de contrato mais vai mais longe deixando estabalecer métodos default ( o java 8 com as suas interfaces com métodos default está na realidade dando opção de implementar traits) .

Eu recomendo dar uma olhada no código-fonte e no JavaDoc do Java Collections Framework, no uso que eles fazem de interfaces e abstract classes. Em específico olhe a Iterable, Collection, AbstractCollection, List, AbstractList, ArrayList, AbstractSequentialList, LinkedList, Set, AbstractSet e TreeSet. Tendo tempo, veja também o Iterator e suas classes implementadoras.

Eles fazem o melhor e mais claro uso de interfaces e abstract classes que conheço.

Hehehe eu suspeitei que os comentários seriam deste tipo… eu conheço bem o que pode e não pode em cada uma, o que eu quero dizer é o seguinte:
Se não existisse Interface eu poderia muito bem utilizar uma classe abstrata para fazer tudo o que ela faz. Ou estou enganado?
As respostas aqui foram todas técnicas, porém o que eu queria desde o começo é uma resposta prática.
Se eu perguntar pra você o porque de eu usar uma Interface e não uma classe abstrata, tem resposta?
Esqueçam o lado “melhor prática” ou “classe abstrata pode implementar métodos, Interfaces não…”

E obrigado pelas respostas ainda assim :smiley:

Em algumas situações você realmente poderia usar classes abstratas ao invés de interfaces. Mesmo tecnicamente possível, é errado, por tudo que já foi citado.

Mas há situações que realmente não é possível. Por exemplo, você não pode criar mixins usando uma classe abstrata - implementar um tipo além do tipo primário da classe. Um exemplo simples?

Você tem a classe Funcionario e a classe Gerente, que herda de Funcionario. Aí você precisa implementar a interface Comparable para o Gerente. Sendo uma interface, tá tranquilo. Mas e se não houvesse interface? Se Comparable fosse uma classe abstrata? Gerente não ia poder herdar de Comparable, por que já herda de Funcionario. Pronto, tá aí uma limitação prática. :smiley:

sim vc falou certo. o q eu quiz dizer é q poderia argumentar q, ainda assim, seria possivel resolver com classe abstrata.

bastava Funcionario e Cliente herdarem de Autenticavel.

[quote=GilsonNunes]sim vc falou certo. o q eu quiz dizer é q poderia argumentar q, ainda assim, seria possivel resolver com classe abstrata.

bastava Funcionario e Cliente herdarem de Autenticavel.[/quote]
Como se Funcionario e Cliente já herdam de Pessoa ?

[quote=digaoneves][quote=GilsonNunes]sim vc falou certo. o q eu quiz dizer é q poderia argumentar q, ainda assim, seria possivel resolver com classe abstrata.

bastava Funcionario e Cliente herdarem de Autenticavel.[/quote]
Como se Funcionario e Cliente já herdam de Pessoa ?[/quote]

eu quiz dizer exatamente o que o digaoneves disse, isso não seria possivel por causa da herança multipla e também o que eu quiz dizer em tudo isso que talvez alguns companheiros não entenderam falando que eu disse que a diferença era herança multipla ou qualquer outra que seja, o que eu quiz dizer é que a interface é bem mais flexiviel fazendo com que entidades diferentes possam implementar comportamento em comum que ambas possuem de formas diferentes fazendo com que o uso de polimorfismo se torne possivel, fazendo também que o software a ser desenvolvido tenha menos acoplamento e alta coesão.

espero ter ajudado

[quote=digaoneves][quote=GilsonNunes]sim vc falou certo. o q eu quiz dizer é q poderia argumentar q, ainda assim, seria possivel resolver com classe abstrata.

bastava Funcionario e Cliente herdarem de Autenticavel.[/quote]
Como se Funcionario e Cliente já herdam de Pessoa ?[/quote]

então era só Pessoa herdar de Autenticavel.

eu entendi o q vcs estão dizendo. só estou frisando q no intuito de entender, eu fazia essas indagações.
q é o mesmo q o autor do tópico está fazendo.

e ele está certo em querer entender a razão q as justificam. mas no meu post eu tentei citar um exemplo prático pra auxiliar no entendimento.

e sei q as coisa não é tão simples assim. vejamos o exemplo do Comparable q tem o CompareTo.

se a classe Object tivesse o CompareTo, tb não resolveria?
ta certo q alguem vai dizer: mas não tem.
mas aí corre o risco de ficar a impressão q a interface veio somente para “corrigir”.

A interface é um contrato, sendo este portanto ela define una e exclusivamente o básico para que alguém interaja com ela.
A classe abstrata é um abstração de comportamentos padrões.
Na pratica, caso a herança múltipla existisse, uma classe abstrata poderia substituir a interface, porém é errado, a nível de design. Considerando no raciocínio do que é possível ser feito, podemos eliminar as classes abstratas também. tanto quanto podemos fazer muitas outra gambiarras que fujam as boas práticas porém funcionem, e na pratica o resultado inicial é o mesmo, porém os problemas a longo prazo são óbvios, quando o estagiário for meter a mão ele vai implementar um método que não pertence a todos, mas a uma parte deles, na classe abstrata, e vai foder com o seu encapsulamento, e assim vai pro buraco a manutibilidade do seu código.
Portanto, na pratica, a uma primeira vista, a interface a a classe abstratas são semelhantes, porém cada uma tem sua aplicabilidade bem definida no projeto do sistema, e que se bem usadas permitem ao sistema existir por mais tempo sem cair na classificação de legado.

mas o fato de usar interfaces, não elimina o uso da classe abstrata, logo esse risco continua existindo.
e ainda, a classe abstrata leva uma vantagem (**ao menos no java): vc poderia implementar algo q fosse util a tds.

**pq em algumas outras linguagens é possivel uma interface implementar metodos. funciona como Helper.

um exemplo prático é a interface OutputStream.

ela tem um metodo Write q escreve um byte.
mas ela não tem um writeBytes, nem um writeInt, etc.
e não seria viável ter, pq forçaria td mundo ter q implementá-los e seria tds idênticos.
mas fosse uma classe abstrata ela poderia implementar visto q ela não precisaria saber como escrever, bastava ela chamar o write q era abstrato.

ou seja, eliminaria a necessidade de um DataOutput e de um DataOutputStream, q a sua unica razão de ser, é a ausência de algo no OutputStream.