Classe Abstrata ou Interface

24 respostas
thegoergen

Qual a diferença entre elas??

Assim: Qual a diferença entre implementar uma interface, implementando todos os métodos , ou herdar de uma classe que tenha métodos abstratos, que terão que ser sobrescritos.??

24 Respostas

antoniopopete

Diferença funcional nenhuma.
Mas em relação a projeto, existe uma diferença significativa.
Quando você fala que vai herdar de uma classe abstrata no seu projeto quer dizer que quem herda é um tipo da classe abstrata, só que especializada.
E o conceito de interfaces, você usa como um serviço que a classe possui.
Quem implementa a interface PersistenciaDAOIf tem que prover todos serviços dessa interface, sem necessariamente ser um PersistenciaDAO.
Mais ou menos assim.
Segue alguns links:

http://www.macoratti.net/net_ica1.htm

http://www.guj.com.br//jforum.java?sourceid=Mozilla-search&module=search&action=search&clean=1&search_keywords=classe+abstrata+x+interface&search_terms=all&sort_by=p.post_time&sort_dir=DESC

http://wickedcoolthoughts.blogspot.com/2008/01/again-abstract-class-vs-interface.html

http://www.mail-archive.com/[email removido]/msg13520.html

J

thegoergen:
Qual a diferença entre elas??

Assim: Qual a diferença entre implementar uma interface, implementando todos os métodos , ou herdar de uma classe que tenha métodos abstratos, que terão que ser sobrescritos.??

Acredito que sua dúvida seja a implementação. Interface apenas uma janela de comunicação entre objetos.

Classes abtratas podes implementar e passar pra frente :wink:

fpavao

Lembrando também que Interface vc pode implementar várias, porém classe abstrata só pode herdar de uma…

sergiotaborda

thegoergen:
Qual a diferença entre elas??

Assim: Qual a diferença entre implementar uma interface, implementando todos os métodos , ou herdar de uma classe que tenha métodos abstratos, que terão que ser sobrescritos.??

Como já foi dito a diferença é no conceito e não na implementação.
Quanto vc usa uma classe abstracta a sua nova classe É-UM tipo da classe mãe.
Quando vc usa uma interface , a classe implementadora PARECE essa interface.

Existe uma grande diferença entre ser e parecer, como compreederá.

Heroi é um classe abstracta. Voador é um comportamento , logo é um interface.
O Heroi pode ser voador, mas nem todos os voadores são Herois (ex: passaro)

T

De modo geral, prefira usar interfaces a classes abstratas (pelo menos enquanto o Java não tiver “mixins” :stuck_out_tongue: )
Eu normalmente faço o seguinte:

  • Crio uma interface;
  • Crio uma implementação padrão para essa interface;
  • Para escrever uma classe que implementa essa interface, posso usar um membro privado que é uma instância dessa implementação-padrão, e delegar vários métodos dessa interface a essa implementação-padrão. Os métodos cuja implementação for diferente da padrão devem ser implementados explicitamente.

Classes abstratas deixam seu programa muito engessado. Às vezes isso é interessante (por exemplo, quando você cria uma servlet estendendo HttpServlet), mas normalmente isso é indesejável.

Paulo_Silveira

prefira sempre o uso de interfaces (e da para sempre usar interfaces em vez de classe abstrata, se voce gastar um pouquinho mais de codigo e fizer composicao). é mais elegante, mais flexivel e menos acoplado… justo porque nao ha heranca de codigo. algumas pessoas consideram heranca uma forte quebra de encapsulamento.

thegoergen

Entendi. :idea:

Valeu pessoal! :lol:

victorwss

Apesar de que há casos (tipo, aquelas interfaces com centenas de métodos), que é melhor herdar de uma classe abstrata.

T

a) Se uma interface tem centenas de métodos há alguma coisa errada nela.
b) Que pena que Java não tem “mixins” igual Scala - aí não estaríamos discutindo essas coisas chatas.

victorwss

thingol:
a) Se uma interface tem centenas de métodos há alguma coisa errada nela.
b) Que pena que Java não tem “mixins” igual Scala - aí não estaríamos discutindo essas coisas chatas.

Infelizmente existem algumas interfaces no java SE e no java EE que tem uma tonelada de métodos. HttpServletRequest é um bom exemplo. Já tentou fazer um façade para HttpServletRequest? Você vai ver que é bem mais conveniente herdar de HttpServletRequestWrapper.

Realmente, mixins é o que me faz mais falta no java e força você a escrever bastante código wrapper, apenas-passa-a-bola-para-frente ou nos piores casos copy-and-paste.

Paulo_Silveira

Essa classe foi criada por uma questao dos frameworks poderem rodar em especificações mais novas, ja que a interface HttpServerRequest muda muito e metodos sao adicionados. Nao foi criada com o intuito de te poupar trabalho nao, nem de ser usada pelos servidores. É que se voce nao estende-la, o dia que entrar um novo metodo na HttpServletRequest, voce vai ter um NoSuchMethodError ao chama-lo na sua facade/proxy.

Intefaces com muitos metodos, como disse o thingol, é sinal de design ruim. Mesmo ocorre com Connection e alguns listeners.

Entendo seu argumento. Esse uso de interfaces que voce esta falando é só para nao ter de escrever algumas duzias de metodos, mas voce poderia facilmente usar composicao em vez de heranca: implementa a interface e delega para a classe, em vez de estende-la. Claro, voce tera de escrever um pouco mais, como ja falei no post anterior, mas qualquer ferramenta gera os delegate methods pra voce. Confesso que as vezes herdo tambem, mas com a plena consciencia de que seria mais elegante fazer como falei aqui

sergiotaborda

Vamos com calma. Muitos métodos numa interface não é sinal de design ruim per se.
Connection tem muitos métodos, mas Connection faz parte de uma implementação do padrão Bridge. É suposto ela ter quantos métodos quiser.

Tudo depende do contexto.

Zakim

Acredito que o objetivo da herança é de amarrar a classe a uma familia de objetos! Criando objetos de verdade e seguindo principios OO. Isso mantem a integridade de toda uma familia de objetos, embora os mantenham um tanto dependentes…

A composição em relação a herança é válida, mas será que vale pra tudo mesmo?

Poderiam citar algum caso em que a herança valha a pena em relação a composição?

Paulo_Silveira

Corretissimo, generalizei demais, mudo a frase para “Interfaces com muitos metodos geralmente indicam um design ruim” (e de qualquer maneira acho a interface Connection muito grande, poderia ter sido quebrada em varias!).

Pra ser sincero, nao vejo nenhum caso. Hoje sou bem xiita que nem o James Gosling, Erich Gamma e Joshua Bloch, que descem a lenha em cima de heranca!

James Gosling:
::Rather than subclassing, just use pure interfaces.
It’s not so much that class inheritance is particularly bad. It just
has problems.::
.

http://www.artima.com/intv/gosling3P.html

No blog da Caelum há tambem um post sobre o assunto:
http://blog.caelum.com.br/2006/10/14/como-nao-aprender-orientacao-a-objetos-heranca/

yoshikichi

Ow, no livro use a cabeca padroesde projetos, o autor fala muito sobre composição, no padrão strategy é q mais fala sobre isso.
pelo q entendi, strategy usa composição.
A pergunta é:
“qndo eu utilizo a composição estou usando o padrao strategy”?
falow

Zakim

Não necessáriamente!

Crie um novo tópico para discutir isso! :stuck_out_tongue:

netShot

Pode mostrar um exemplo pratico de uso de interfaces + composição e outro com classe abstratas ? Acho que fica melhor explicado.

Abraços

tnaires

Estou ressucitando este tópico para discutir um caso especial:

Paulo Silveira:
Pra ser sincero, nao vejo nenhum caso. Hoje sou bem xiita que nem o James Gosling, Erich Gamma e Joshua Bloch, que descem a lenha em cima de heranca!
Paulo, neste link o autor expõe um exemplo onde a herança seria adequada:
class Transacao {

}

class Reserva extends Transacao {

}

class Compra extends Transacao {

}
E justifica com o texto abaixo ( traçando um paralelo entre as 5 regras que regem o uso de herança ):
- Regra 1 (tipo especial): ok. Uma Reserva é um tipo especial de Transação e não um papel assumido por uma Transação - Regra 2 (mutação): ok. Uma reserva sempre será uma Reserva, e nunca se transforma em Compra (se houver uma compra da passagem, será outra transação). Idem para Compra: sempre será uma Compra - Regra 3 (só estende): ok. Ambas as subclasses estendem Transação com novas variáveis e métodos e não fazem override ou anulam coisas de Transação - Regra 4 (não estende classe utilitária): ok. - Regra 5 (tipo especial de papel/transação/dispositivo): ok. São tipos especiais de Transação
Você concorda com a análise dele? Se discordar, em quais pontos? Na sua opinião, seria coerente forçar a composição afirmando que uma Transacao tem um tipo, e não é de um tipo?

Abraços

P.S. - direcionei a questão ao Paulo por causa de sua afirmação citada no início do post, mas gostaria de saber a opinião da galera do fórum também.

tnaires

Só dando um up…

pcalcado

Eu acho meio hipócrita do Gosling ou qualquer outro envolvido com a criação de Java falar mal de herança. O grande problema é que Java não oferece nenhum mecanismo para reuso de código comparável a herança. Se houvessem mixins ao menos...

tnaires:
class Transacao {
}

class Reserva extends Transacao {

}

class Compra extends Transacao {

}

Não dá para dizer. Sem conhecer o domínio e a implementação qualquer exemplo é falho. O que é uma Transação neste contexto? Eu já trabalhei para alguns bancos e cada um tem um conceito diferente, mesmo várias definições dentro da mesma instituição.

Eu não sou xiita quanto a isso simplesmente porque já vi muita besteira sendo feita em nome de "herança é ruim, use composição". Isso é uma rule of thumb e não uma lei. Como falei antes o design de Java faz com que seja muito difícil resolvermos problemas comuns sem heranças ou gambiarras (strategy de uma implementação só e o fim).

Para mim, a decisão entre delegação e herança passa pelo domínio e este é o principal juiz. Esta delegação faz sentido no domínio? Eu dificilmente criaria uma classe extra na Camada de Negócios só para satisfazer uma rule of thumb.

Ps: Tarso, dar up é muito feio.

tnaires

Desculpe :oops: … Você acreditaria se eu dissesse que pensei mil vezes antes de fazer isso? Fiz porque a rotatividade do Java Básico é muito alta, e também porque não encontrei outra opção de torná-lo visível novamente.

Entendo. Aparentemente trata-se de uma transação financeira e não bancária. O contexto no qual o exemplo se encaixa é muito vago, não dá mais detalhes sobre o domínio.

Pois é… Eu estava falando justamente isso pra um amigo meu que leu sobre isso há pouquíssimo tempo, e ficou xiita quanto à herança. Quando algumas pessoas se deparam com esse "mantra" pela primeira vez, ficam tão impressionadas que passam a abominar totalmente seu uso. Isso ocorre porque elas vinham utilizando herança em todas as situações que requeriam apenas composição ( o caso Pessoa -> PessoaFisica é clássico ).

faelcavalcanti

para implementações como nas classes de stream no pacote java.io, utilizando a concepção do pattern decorator.

faelcavalcanti

um exemplo de composição a partir de interfaces você pode visualizar a partir deste modelo abaixo pelo padrão observer:

já para um modelo com classes abstratas, seria o mesmo padrão utilizando as classes no pacote java.util, como Observable. neste caso prefiro o 1º caso.

tnaires
faelcavalcanti:
um exemplo de composição a partir de interfaces você pode visualizar a partir deste modelo abaixo pelo padrão observer:
Outro exemplo é o padrão Strategy:
interface Strategy {
    void doStrategy();
}

class ConcreteStrategy1 {
    void doStrategy() {
        System.out.println("Strategy 01");
    }
}

class ConcreteStrategy2 {
    void doStrategy() {
        System.out.println("Strategy 02");
    }
}

class Client {
    private Strategy strategy;

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }
}
http://en.wikipedia.org/wiki/Strategy_pattern
Criado 14 de abril de 2008
Ultima resposta 13 de out. de 2008
Respostas 24
Participantes 14