Interface x Clase abstrata

pessoal foi mal.
o OutputStream não é interface não.

me desculpem a confusão ai.

Você não pode reescrever qualquer código com interfaces usando classes abstratas.

Por pensar assim, você está considerando que:
a) Você sempre pode reescrever a interface na forma de uma classe abstrata;
b) Você tem total controle sobre todas as partes do código.

Esse pensamento não é válido se você estiver lidando com uma biblioteca de terceiros, ou criando uma biblioteca para terceiros utilizarem.

Tente resolver esse problema com classes abstratas. Considere que as ProcessoPesado e Desenhavel são interfaces duas bibliotecas diferentes, que não foi implementada por você, nem pela mesma pessoa.

[code]public interface ProcessoPesado {
void processar();
}

public interface Desenhavel {
void desenhar(Graphics2D g);
}

public class Exemplo implements ProcessoPesado
{
public void processar() {
//Faz qualquer processamento pesado aqui
}
}

public class Exemplo2 extends Exemplo implements Desenhavel {
public void desenhar(Graphics2D g) {
//Faz um lindo desenho aqui
}
}
[/code]

Como você reescreveria esse código, caso as bibliotecas tivessem fornecido classes abstratas?

Lembre-se que as bibliotecas provavelmente terão métodos como:

void executarProcessoNoAzureServer(ProcessoPesado p);
void desenharUsandoDirectX(Desenhavel d);

E que, como você baixou essas bibliotecas na forma de um .jar compilado, você não pode alterar o parâmetro de entrada desses métodos.

As interfaces são legais pelo que o Sergio falou. Aqui, a lib externa está apenas preocupada no comportamento do que quer que seja passado para ela.
Não interessa o que seja um processo pesado, desde que ele tenha o comportamento de “processar()”.
Não interessa também o que seja um Desenhavel, desde que ele tenha o comportamento de “desenhar()”.

Desde que a classe de quem usa a lib, não importando onde esteja na hierarquia, diga que está de acordo com esse comportamento (ou seja, ela está de acordo com o “contrato”), então, ela poderá ser usada pela lib.

Note que isso vale se você também estiver escrevendo uma biblioteca para outros usarem. Ao declarar suas interfaces, você diz quais métodos espera que uma classe tenham, e fornece um serviço para quem implementa-los, sem se preocupar com que classe exatamente faz isso.

Olá

em relação a pergunta concreta do pedroe

acho que a resposta está aqui:

http://docs.oracle.com/javase/specs/jls/se7/html/jls-9.html

Chapter 9. Interfaces
[…]
Programs can use interfaces to make it unnecessary for related classes to share a common abstract superclass or to add methods to Object.
[…]
Que numa tradução livre se pode entender como:
“Os programas podem usar interfaces para tornar desnecessária, para as classes relacionadas, compartilhar uma superclasse abstrata comum ou para adicionar métodos para a Object.”

Lendo isso ao contrário, acho que fica claro que a resposta é sim. O contexto é que determina o que deverá ser usado.

Abs.

[quote=joagostini]Olá

em relação a pergunta concreta do pedroe

acho que a resposta está aqui:

http://docs.oracle.com/javase/specs/jls/se7/html/jls-9.html

Chapter 9. Interfaces
[…]
Programs can use interfaces to make it unnecessary for related classes to share a common abstract superclass or to add methods to Object.
[…]
Que numa tradução livre se pode entender como:
“Os programas podem usar interfaces para tornar desnecessária, para as classes relacionadas, compartilhar uma superclasse abstrata comum ou para adicionar métodos para a Object.”

Lendo isso ao contrário, acho que fica claro que a resposta é sim. O contexto é que determina o que deverá ser usado.

Abs.[/quote]

Releia o tópico que você verá que foram apresentados argumentos sobre situações onde não é possível empregar uma classe abstrata.

Olá wagnerfrancisco

Não discordo disso. Acho que se não existisse a interface, algo teria que ser feito para implementá-la.
Apenas me restringi à intenção da pergunta: saber se é possível fazer com uma classe abstrata o que se faz com uma interface. Sim, é possível.
Agora, posso fazer tudo com uma classe abstrata, prescindindo de uma interface? Não, não é possível. As várias respostas do tópico mostraram isso.
As duas classes são diferentes, com propósitos diferentes. Portanto, usos diferentes.
Entretanto, há várias possibilidades de se usar uma classe abstrata que dispensariam o uso da interface, mas não a eliminam e nem a substituem.
Depende do caso concreto.

Sim. Aí entra no mérito de “ser possível” e “ser inteligente”.

Muita coisa é “teoricamente possível”, mas é inadequada e trará problemas no futuro.

Depender seu código de implementações no lugar de interfaces é uma delas.

Até porque, isso gera transtornos incríveis, caso você esteja programando uma lib para alguém.

Desculpem se ainda não me convenci das respostas, mas vou argumentar novamente.

Quando digo classe abstrata estou me referindo mais especificamente a métodos abstratos.

Por exemplo:

public interface Foo {
    void jump();
}

public abstract class Foo {
    abstract void jump();
}

Qual a diferença entre as duas implementações?
Em ambas eu defino um contrato a ser seguido. Se eu criar uma classe que só possua métodos abstratos, não irei estar criando uma espécie de interface?

Este é um exemplo de quem defende a Interface por ser “herança multipla”. Nesse exemplo eu concordo, mas se observar no meu primeiro post do tópico, eu quero justamente encontrar uma explicação diferente desta, pois acho que existe um motivo para a existencia de Interfaces além deste.

[quote=pedroe]Desculpem se ainda não me convenci das respostas, mas vou argumentar novamente.

Quando digo classe abstrata estou me referindo mais especificamente a métodos abstratos.

Por exemplo:

public interface Foo {
    void jump();
}

public abstract class Foo {
    abstract void jump();
}

Qual a diferença entre as duas implementações?[/quote]

As diferenças são as seguintes:
a) Na segunda, quem herdar essa classe cria uma relação de tipos (como explicado pelo Sérgio). Essa relação é muito mais forte do que simplesmente o cumprimento de um contrato.
b) Na primeira, há a garantia de que nenhum programador irá incluir ali um atributo ou método implementado;
c) A segunda pode ser implementada em qualquer nível da hierarquia de classes de seu usuário;

Sim. Toda classe abstrata também define uma espécie de contrato. Entretanto, a relação é muito mais forte, pois você está criando um compromisso com a implementação, e não só com o comportamento. Esse compromisso existe mesmo que, a princípio, sua classe esteja vazia - como a que você colocou. Afinal, nada impede que com o passar do tempo, no decorrer do projeto, alguém modifique ali e inclua atributos e métodos com código.

Dizer que você é um subtipo de outro é uma das relações mais fortes que existem em OO. Ela geralmente implica em ter que revisar o comportamento da classe filha, caso o da classe pai mude.
Entretanto, dizer que você só implementa um contrato de comportamento é uma relação fraca.

Em algumas linguagens, como o C++, criar uma classe abstrata sem implementações é uma das únicas formas de se declarar interfaces. Entretanto, nesse caso, você está contando com a boa vontade e a capacitação técnica dos programadores para não incluírem lá métodos com comportamento ou atributos. Isso é o tipo de coisa que chamamos de “abordagem sujeita a erros”, pois aquele membro menos capacitado da equipe pode ir até lá e fazer caquinha.

O que está te complicando é que esse motivo é conceitual. A implementação dos conceitos de interface e classe abstrata é muito similar (para não dizer, idêntica, como no caso do C++). Você dificilmente vai ver no código mais do que uma simples palavra chave e, no máximo, algumas restrições de uso. Entretanto, os conceitos em si são muito diferentes e usar um ou outro tem consequências a longo prazo.

A palavra chave interface reforça uma promessa: a de que aquele compromisso é de comportamento, e continuará sendo de comportamento. Você vai notar que o desenvolvimento de software é basicamente formado de compromissos de diferentes tipos entre uma classe e outra e, deixa-los absolutamente claros e, preferencialmente, verificados pelo compilador, é o que torna os sistemas robustos.

ViniGodoy, obrigado pela resposta e pela paciência, vou aceitar o que você colocou.
Continuo com o pensamento de que tecnicamente eu posso usar uma classe abstrata para fazer o papel de uma interface, deixando de lado o fato de alguém poder implementar um método na classe abstrata, ou da ligação mais forte de herança que você comentou, pois isso são questões teóricas (de boas práticas), mas que não me impedem na prática, certo?
Claro que estas questões que você levantou estão corretíssimas, e eu defendo sim o uso de interfaces. Eu só queria tirar a prova na questão prática mesmo.

Valeu!

[quote=pedroe]ViniGodoy, obrigado pela resposta e pela paciência, vou aceitar o que você colocou.
Continuo com o pensamento de que tecnicamente eu posso usar uma classe abstrata para fazer o papel de uma interface, deixando de lado o fato de alguém poder implementar um método na classe abstrata, ou da ligação mais forte de herança que você comentou, pois isso são questões teóricas (de boas práticas), mas que não me impedem na prática, certo?
[/quote]

Errado. Mas continue pensando assim e trabalhando assim. Quando um dia vc se ferrar ai vc vai entender porque as questão teóricas são mais importantes que a prática.

[quote=sergiotaborda][quote=pedroe]ViniGodoy, obrigado pela resposta e pela paciência, vou aceitar o que você colocou.
Continuo com o pensamento de que tecnicamente eu posso usar uma classe abstrata para fazer o papel de uma interface, deixando de lado o fato de alguém poder implementar um método na classe abstrata, ou da ligação mais forte de herança que você comentou, pois isso são questões teóricas (de boas práticas), mas que não me impedem na prática, certo?
[/quote]

Errado. Mas continue pensando assim e trabalhando assim. Quando um dia vc se ferrar ai vc vai entender porque as questão teóricas são mais importantes que a prática.[/quote]
Sérgio, esse discurso do pedroe é compreensível quando não se tem ainda uma experiência que garanta coisas como a necessidade de usar uma classe abstrata de terceiros que foi mal implementada e que seria super simples caso fosse uma interface.

… e a possibilidade de implementar várias interfaces…

Certo. Deixando de lado todas as diferenças, são iguais. :lol:

No caso, a ligação forte não é boa prática, é uma questão de projeto. É como decidir se você cria um filho ou usa composição. As duas podem, teoricamente, fazer a mesma coisa. Mas ambas implicam em consequências de projeto diferentes a longo prazo.

Todas as limitações das interfaces e a possibilidade de “herança múltipla” são para justamente reforçar esse conceito teórico. Em termos técnicos, não duvido que o compilador as trate como uma espécie de classes abstratas mesmo. Ou, como no caso do C++, elas efetivamente sejam classes abstratas.

Agora, é importante diferenciar entre a existência de um conceito e sua implementação. No C++, por exemplo, existe com templates uma forma curiosa de implementar o conceito de interfaces, que não envolve criar uma classe, ou sequer declarar a interface em lugar nenhum (exceto seu diagrama UML).

Você pode fazer um método assim:

template <typename T> public void soma(T[] v1, T[] v2, int size) { for (int i = 0; i < size; ++i) v1[i] += v2[i]; }

Não existe uma definição para “T” além dessa.

Então, onde está a interface nessa função? Está implicita.
Basicamente “T” pode ser qualquer coisa que você pudesse fornecer para a função, e que não desse erro de compilação.

Por exemplo, poderia ser dois arrays primitivos de int ou float. Note que esse código funcionaria perfeitamente com eles.
Poderia ser também dois vector (equivalente ao List, do java). No C++, o operador de [] é sobrecarregado num vector e, portanto, poderia ser usado nesse contexto.
Poderia ser também dois Vector2, de uma biblioteca matemática, como a que implementei na ForFun. Enfim, poderia ser qualquer coisa que tivesse os operadores de [] sobrecarregados, e que o resultado desses operadores fossem somáveis (inclusive 2 arrays de std::string, onde ele faria a concatenação de todos os elementos, já que a string, no C++, é mutável e suporta o +=).

Ou seja, a interface aqui está definida única e exclusivamente pelo comportamento, e não pela necessidade de uma classe dizer que “implementa uma interface”. Qualquer classe que o programador forneça para esse método, que se comporte como o código assume que se comporte, serve. Vê? É uma forma completamente diferente de se implementar exatamente o mesmo conceito.

A forma que se escolhe para implementar um conceito geralmente vai implicar em limitações da linguagem, ou a existência ou não de verificações do compilador, etc… Agora é importante compreender o conceito e o que ele representa em termos de projeto, pois a linguagem é só a forma que temos para expressar isso para o computador.

Na prática pode até funcionar.

Nada impede você de iterar um array que contém o alfabeto, e invocar um método que retorna uma String via reflection pra formar o seu nome e imprimir em um System.out.print

Nada impede você de fazer um sistema onde a camada de controle da view, as regras de negócio e a persistência estão implementadas em uma classe só, no seu “Sistema.java”

Mas eu não recomendaria nada disso…

sergiotaborda, da pra ver que você possui dificuldade em compreender e interpretar textos, mas isso é normal pra maioria, infelizmente. Eu conheço o que é melhor em sentido de projeto, e sei da importância da interface. Eu abri este tópico única e exclusivamente para ter certeza que em termos prático não haveria diferenças. Se observares o primeiro post desse tópico, eu cito a questão de poder implementar várias interfaces, mas que gostaria de saber se havia alguma outra vantagem prática (de código mesmo).

[quote]… e a possibilidade de implementar várias interfaces…

Certo. Deixando de lado todas as diferenças, são iguais. [/quote]

ViniGodoy, era exatamente isso que eu estava buscando como resposta. Não pensem que eu não entendi as vantagens de se usar interface, até porque eu já as conhecia. Deixando de lado questões de projeto, de pegar uma classe abstrata implementada por terceiros, etc e etc. O que me impediria (que seria um impasse de fato) eu meu próprio código, é isso o que eu estava buscando (mais uma vez dizendo que a questão de “herança múltipla” já era do meu conhecimento).

Obrigado a todos!

sergiotaborda, da pra ver que você possui dificuldade em compreender e interpretar textos, mas isso é normal pra maioria, infelizmente. Eu conheço o que é melhor em sentido de projeto, e sei da importância da interface. Eu abri este tópico única e exclusivamente para ter certeza que em termos prático não haveria diferenças. Se observares o primeiro post desse tópico, eu cito a questão de poder implementar várias interfaces, mas que gostaria de saber se havia alguma outra vantagem prática (de código mesmo).
[/quote]

Vc faz me lembrar aquele cara que esta se afogando e pediu que Deus o salvasse. Ai chega um barco e quer salvar o cara, mas o cara responde “não obrigado, Deus vai-me salvar” e isso acontece várias vezes até que Deus perde a paciencia e fala "Cara, deixa de ser chato, já te mandei 3 barcos "

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.

Se vc colocar num diagrama de Vernn o que dá para fazer com um e com outro são conjuntos dijuntos.
Existe uma intersecção não vazia. Sim existe, mas isso é inconsequente.

Ai vc vem com essa de "Eu abri este tópico única e exclusivamente para ter certeza que em termos prático não haveria diferenças. " e todo o mundo lhe disse que ha diferenças. Tanto práticas quanto teóricas. Mas vc insiste em querer que lhe digam que não , que não ha diferença.

[/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 ? :shock:

Vai ver eu estou louco e realmente não sei ler, mas esta conversa me parece conversa de surdos. Vc não quer ouvir a resposta real.
Então tá, Não existe diferença nenhuma, e como eu disse antes, continue pensando assim. Quando cair a ficha que todos os barcos passaram, não venha chorar que ninguém o salvou.

[quote=drsmachado][quote=sergiotaborda][quote=pedroe]ViniGodoy, obrigado pela resposta e pela paciência, vou aceitar o que você colocou.
Continuo com o pensamento de que tecnicamente eu posso usar uma classe abstrata para fazer o papel de uma interface, deixando de lado o fato de alguém poder implementar um método na classe abstrata, ou da ligação mais forte de herança que você comentou, pois isso são questões teóricas (de boas práticas), mas que não me impedem na prática, certo?
[/quote]

Errado. Mas continue pensando assim e trabalhando assim. Quando um dia vc se ferrar ai vc vai entender porque as questão teóricas são mais importantes que a prática.[/quote]
Sérgio, esse discurso do pedroe é compreensível quando não se tem ainda uma experiência que garanta coisas como a necessidade de usar uma classe abstrata de terceiros que foi mal implementada e que seria super simples caso fosse uma interface.
[/quote]

Quando vc está na faculdade e o professor lhe diz algo, ou quando seu pai lhe diz algo, vc pode simplesmente não acreditar. Mas vc estará sendo louco se achar que eles estão mentindo. Uma coisa é vc não ter experiencia e não entender o que lhe dizer, outra é não querer entender e outra pior é não querer aceitar. Se a pessoa não aceita o que é óbvio ela continuará vivendo, mas com menos qualidade do que poderia. Me lembra o velho problema do pessoa que não quer acreditar que MVC não é separação em camadas. Existe um limite para o como e de quantas formas podemos explicar o óvibo. O resto advém da aceitação e o resto advém da experiancia.

Eu sei que ha pouco experiencia envolvida, mas é mais do que isso, é uma teimosia estranha em não aceitar o que todo o mundo já falou.
Passar a mão na cabeça e dizer que sim, é isso mesmo, é paternalismo : não estamos aqui para ser paternalistas. Estamos aqui para tentar transmitir conhecimento. Mais do que isso, transmitir valores.

Olás

Mesmo sabendo bem menos e sem querer polemizar com ninguém, apenas estou me esforçando para entender tudo o que foi dito, tento dar meu pítaco.
O trecho abaixo foi tirado dos documentos da Oracle sobre o tema em questão. É longo, mas para os neófitos como eu , acredito que será de interesse ler.

Esse texto tenta responder as seguintes perguntas do pedroe

[quote]
Qual a diferença entre as duas implementações?
Em ambas eu defino um contrato a ser seguido. Se eu criar uma classe que só possua métodos abstratos, não irei estar criando uma espécie de interface?[/quote]

O texto traduzido:

Interfaces

Há uma série de situações em engenharia de software quando é importante para diferentes grupos de programadores concordar com um “contrato” que indica como seu software interage com os demais. Cada grupo deve ser capaz de escrever seu código, sem qualquer conhecimento de como o código do outro grupo está escrito. De um modo geral, as interfaces são contratos.

Por exemplo, imagine uma sociedade futurista, onde carros robóticos controlados por computador transportam passageiros pelas ruas da cidade sem um operador humano. Os fabricantes de automóveis escreverão software (Java, é claro) que opera o automóvel para que ele pare, de a partida, acelere, vire à esquerda, e assim por diante. Outro grupo industrial, fabricantes de instrumentos eletrônicos de orientação, farão sistemas de computadores que recebem dados de GPS para se pocisionar e as condições de tráfego para dirigir o carro com essas informações.

Os fabricantes de automóveis, então, devem publicar uma interface padrão dessa indústria que explica em detalhes o que métodos chamados podem fazer para movimentar o carro (qualquer carro, de qualquer fabricante). Os fabricantes poderão então escrever softwares que chamarão os métodos descritos na interface para comandar o carro. Nenhum grupo industrial precisa saber como o software do outro grupo é implementado. De facto, cada grupo considera seu software altamente proprietário e se reserva o direito de modificá-lo a qualquer momento, enquanto continua aderindo a interface publicada.

No exemplo do carro robótico acima, serão os fabricantes de automóveis que irão implementar a interface. A implementação da Chevrolet será substancialmente diferente da Toyota, é claro, mas ambos os fabricantes aderem à mesma interface. Os fabricantes de orientação, que são os clientes da interface, irão construir sistemas que utilizam os dados de GPS sobre a localização de um carro, mapas digitais de rua, e dados de tráfego para dirigir o carro. Ao fazer isso, os sistemas de orientação irão chamar os métodos de interface: transformar, pistas de mudança, de freio, acelerar, e assim por diante.

Interfaces e herança múltipla

Interfaces tem outro papel muito importante na linguagem de programação Java. Interfaces não fazem parte da hierarquia de classes, apesar de trabalharem em conjunto com as classes. A linguagem de programação Java não permite herança múltipla, mas as interfaces fornecem uma alternativa.

Em Java, uma classe só pode herdar parâmetros e métodos de apenas uma classe, mas pode implementar mais de uma interface. Portanto, os objetos podem ter vários tipos: o tipo de sua própria classe e os tipos de todas as interfaces que ela implementa. Isto significa que se uma variável é declarada para ser o tipo de uma interface, o seu valor pode fazer referência a qualquer objeto que é instanciado a partir de qualquer classe que implementa a interface.

Classes abstratas vs Interfaces

Ao contrário de interfaces, classes abstratas podem conter campos que não são static e final, e podem conter métodos implementados. Tais classes abstratas são semelhantes às interfaces, exceto que eles fornecem uma implementação parcial, deixando à subclasse concluir a implementação. Se uma classe abstrata contém apenas declarações de métodos abstratos, deve ser declarado como uma interface em vez de classe abstrata.

Multiplas interfaces podem ser implementadas por uma classe em qualquer lugar na hierarquia de classes, estejam ou não relacionadas umas com as outras.

Em comparação, classes abstratas são mais comumente subclasses que compartilham pedaços de implementações. Uma única classe abstrata é uma subclasse de classes semelhantes que têm muito em comum (as partes implementadas da classe abstrata), mas também têm algumas diferenças (os métodos abstratos).

Pelo exposto, fica claro que a interface java tem duas funções, servir como um “interface pública” para determinadas implementações de software e permitir que as classes possam ter herança múltipla.

Pelo exposto, no que concerne ao papel de “interface pública”, não há como tecnicamente fazer uma classe abstrata agir desse modo. Para isso ela teria que ser a superclasse de todas as demais classes, o que não permitiria implementar nenhuma “interface pública”! Pois todos os métodos abstratos serão implementados nas subclasses e estas não se comunicarão. [Por favor, digam se o meu arrazoado está certo]

Pelo que entendi, a única possibilidade técnica, como o pedroe tentava descobrir, de fazer uma classe abstrata funcionar como uma interface está exatamente no papal de suprir a herança múltipla. Essa “possibilidade técnica” é apenas no sentido de alguém que não tá afim de fazer nada direito e resolve escreve tudo em uma classe abstrata. Mas se fizer isso, não dará erros e o aplicativo rodará. [idem]

Escrevi sobre isso não desprezando nenhuma das argumentações e explicações dadas, apenas procurei encontrar o meu entendimento e expus aqui para que o avaliem. Nada do que foi escrito aqui tem a intenção de substituir o que já foi dito. É apenas um exercício.
Abs.

[quote=joagostini]Pelo que entendi, a única possibilidade técnica, como o pedroe tentava descobrir, de fazer uma classe abstrata funcionar como uma interface está exatamente no papal de suprir a herança múltipla.
[/quote]

mas o “papel de herança múltipla”, é exatamente o q a classe abstrata não poderá suprir.

pelo q eu entendo, essa é exatamente uma coisa q só se consegue no java com uso de interfaces.

não só no java, mas tb na maioria das outra linguagens.

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.