Interface x Clase abstrata

[quote=joagostini]GilsonNunes

O meu raciocínio é o seguinte.
Imagine uma classe chamada Casa, onde se descreve todos os cômodos de uma casa em termos de suas dimensões.
Crio uma classe Empreiteiro que estende casa, e que com base nas dimensões calcula quanto tempo que irá demorar para construir a casa.
O dono das classes decidiu, que além do tempo, quer saber o custo de cada cômodo.
Em vez de criar uma interface Custo implementando-a em Empreiteiro, ele faz de Casa uma classe abstrata e declara um método abstrato quantoCusta();.
Em Empreiteiro ele implementa o método para cada cômodo.
Nesse momento é como se fosse uma herança de outra classe, pois o cidadão pois os dois na mesma classe.
É assim que entendi a possibilidade de usar uma classe abstrata como se fosse uma interface.[/quote]

mas eu não consigo ver o q isso tem a ver com múltipla herança.

Gilson

Talvez seja melhor que vc diga porque não seria a simulação de múltipla herança.
Já que o que descrevi nada mais é que como se pode usar uma classe abstrata, que no caso ao invés de assinar um método abstrato correlato aos métodos declarados da classe, traz consigo elementos do que seria uma outra classe.

[quote=joagostini]Gilson

Talvez seja melhor que vc diga porque não seria a simulação de múltipla herança.
Já que o que descrevi nada mais é que como se pode usar uma classe abstrata, que no caso ao invés de assinar um método abstrato correlato aos métodos declarados da classe, traz consigo elementos do que seria uma outra classe.[/quote]

multipla herança, seria se um objeto Empreiteiro precisasse se passar por Custo.
o fato de agora ele ter um metodo com nome e assinatura igual ao da classe Custo, não significa q o compilador vai achar q ele é um Custo.

onde se pede um Custo, aceita um Custo ou seus derivados, no caso de Custo ser classe;
ou um q implemente, caso Custo seja interface (aki é q dá vida à “múltipla herança”, já q o tal poderia herdar de qq coisa).

[quote=GilsonNunes]

multipla herança, seria se um objeto Empreiteiro precisasse se passar por Custo.
o fato de agora ele ter um metodo com nome e assinatura igual ao da classe Custo, não significa q o compilador vai achar q ele é um Custo.

onde se pede um Custo, aceita um Custo ou seus derivados, no caso de Custo ser classe;
ou um q implemente, caso Custo seja interface (aki é q dá vida à “múltipla herança”, já q o tal poderia herdar de qq coisa).[/quote]

Olha, acho que vc está definindo outra coisa.
Peguei esta definição de herança aqui http://www.dca.fee.unicamp.br/cursos/PooJava/heranca/index.html

Herança
Herança é um mecanismo que permite que características comuns a diversas classes sejam fatoradas em uma classe base, ou superclasse. A partir de uma classe base, outras classes podem ser especificadas. Cada classe derivada ou subclasse apresenta as características (estrutura e métodos) da classe base e acrescenta a elas o que for definido de particularidade para ela.

Nessa definição não há referência a que um objeto se passe por outro, mas que um objeto herda estrutura e métodos da super classe e acrescenta os seus próprios. Dessa forma, Empreiteiro dá origem ao objeto empreiteiro que usa, entre outros, métodos do objeto casa para realizar as suas funções de empreiteiro. Analogia com seres humanos: herdei características dos meus pais, mas não sou nem um e nem outro, sou eu apenas com herança.
O que pensei em base ao que pedroe questionva seria o uso errado de uma classe abstrata inserindo nela parâmetros e métodos de dois objetos diferentes. Um com métodos descritos, outra com métodos abstratos, que seriam definidos na subclasse. Isso fingiria que a subclasse herdaria métodos de “dois objetos diferentes”.

sergiotaborda, vamos lá então, hehe.

Seguinte: imagine que tenho uma classe abstrata apenas com métodos abstratos. Essa classe eu estou implementando para mim, nunca ninguém além de mim irá utilizá-la. Eu nunca vou disponibilizar essa classe em alguma biblioteca para ser usada por outros, e também nunca vou deixar algum programador mexer nessa classe e implementar algum método, ou fazer alguma coisa errada. Resumindo, eu sei que essa classe só deve possuir métodos abstratos, e ela permanecerá assim. Neste cenário, qual a vantagem de utilizar interface?
Tirando o fato de que com interface eu posso ter uma “herança múltipla” (implementando várias interfaces).

[quote]É. Vc estava buscando. Mas a frase é sarcástica e vc não entendeu isso. Se “Deixando de lado todas as diferenças” são iguais, quer dizer que ha diferenças.É como dizer que “O homem e a mulher, deixando de lado todas as diferenças, são iguais.” Entendeu ?

Pior de tudo é que vc ainda afirma que sabe que existem diferenças e quais elas são, mas mesmo assim vc insiste em quere que lhe digam que não diferenças ?
[/quote]

Cara, as diferenças que eu disse que conheço são teóricas (e.g. melhores práticas de se programar, pensando no lado de projeto, de como ficará o visual do código, etc) mas não limitações práticas! Entenda isso por favor. Ninguém até agora me deu um exemplo do tipo “cara, se você tiver que fazer isto: xxx… você só conseguirá fazer com interface”.

O ViniGodoy não me deu uma resposta sarcástica ao meu ver. E se deu o problema é dele, com todo o respeito. Pense no seguinte: se você herdar uma classe abstrata, não poderá herdar outra. Se usar interface ao invés da classe abstrata, poderá implementar diversas interfaces. Isto é uma limitação técnica quando se usa classes abstratas!.
É isso o que eu quero. Porém este exemplo eu já conheço e citei no primeiro post. Eu só quero ver se existe outro exemplo como este.

Eu tenho muita experiência em Java meu caro, programo há anos, e isso não quer dizer que eu seja um guru. Essa dúvida só me surgiu agora.
E se a “classe de terceiros que foi mal implementada” tivesse sido bem implementada? O que eu quero deixar de lado é esta questão de “pode ser, pode não ser”. Eu quero a limitação técnica. Eu não estou dizendo que se ninguém me der uma resposta pra essa pergunta eu vou passar a só usar classe abstrata. Eu defendo interface! Pelos termos já citados de projeto, de que lá na frente pode surgiu algum problema. Mas quero por curiosidade saber da questão técnica, prática.

[quote]Existe sim diferença teórica e prática entre classe abstrata e interface. Se não existisse, não precisaria de dois contrutos.
Vc consegue fazer quase tudo o que faz com uma, com o que faz com outra, mas não tudo.[/quote]

O que não posso fazer então?

[quote=pedroe]
O que não posso fazer então?[/quote]

Não vou repetir o que já foi dito, mas resumindo

Interface - I

Define um contrato publico
Não define Identidade (É-UM)
Apenas define contratos públicos.

Classe Abstrata - A

Define um contrato publico
Define Identidade (É-UM)
Não apenas define contratos públicos. Podendo definir contratos em qualquer nível de visibilidade (publico, protegido ou de pacote)

I intersecção A

Define um contrato publico. É só isto que têm em comum. Nada mais.

O seu exemplo de uma classe abstrata que só vc usar, etc, etc… é vazio. OO não está nem ai para o programador que usa a classe. Ela está ai para como as outras classes a usam.
Se vc define uma classe puramente abstrata com apenas metodos publico vc não tem o mesmo efeito que uma interface. Está claro isto ? Porquê ? Porque ao definir o conceito como uma classe abstrata vc está dizendo que aquele conceito é a responsabilidade primária da classe. Exemplo do Calendar que é uma classe abstrata. O que é Calendar não é mais coisa nenhuma. Atenção ao verbo ser. A classe abstrata define a relação É-UM automaticamente. Não tem como vc evitar isso. Portanto ela é intrinsecamente diferente de uma interface que nunca conseguirá definir esta relação.

Ambas as opções são diferentes intrinsecamente. Até o bytecode é diferente.

Pode parecer , à primeira vista, que uma classe puramente abstrata com métodos públicos é equivalente a uma interface. Simplesmente não é.

Isto


public abstract  class XPTO {

}

e isto,


public interface XPTO {

}

são equivalentes ? Repare que não ha nenhum método…

Não. não são equivalentes.
Não sei como lhe explicar isso melhor senão dizendo que uma define relação É-UM e a outra não.

Se elas não são equivalentes quando vazias, por maioria de razão, não o serão quando tiverem métodos - não importa quais. Elas já são diferentes à partida.
Ao tomar a decisão entre uma e outra ha um trade-off, portanto não ha equivalência.

A interface sempre têm vantagem porque ela pode ser a raiz de uma hierarquia ou não. A classe abstrata sempre é.
Eu , por exemplo, sempre defino meus conceitos OO como interfaces. E só mais tarde, se descobrir que precisa forçar a identidade desde o inicio que mudo para abstrato. Normalmente eu definio o conceito como interface porque me permite programar para a interface sem precisar pensar como será implementado. Depois eu crio uma classe abstrata se a interface tem muitos métodos comuns às implementações. Se isso foi muito forte, então significa que o conceito por si mesmo me força a considerar uma herança forte , e nesse momento eu renomeio a classe abstrata para o nome da interface e removo a interface. Mas isto é raro. A estrutura Interface A <- class abstrata AbstractA <-- os outros costuma funcionar muito bem (não é por acaso que é a base da API de collections)

Bom, se ainda não ficou claro, alguém que explique. Eu não tenho mais palavras.