Bom, mesmo quando é uma única pessoa que define um grande sistema há algumas diferenças de projeto…
Imagine quando é um monte delas.
A hierarquia das classes do java.io apareceu já no Java 1.0 (não tenho certeza, já que não tenho nenhum JDK 1.0 aqui comigo para confirmar tal afirmação).
Pelo menos no Java 1.1 (que é aquele que até a Microsoft implementou) a hierarquia é assim:
Object -> InputStream -> FilterInputStream -> BufferedInputStream
Mas a hierarquia das classes do Collection Framework, que é bem mais organizada, só apareceu no JDK 1.2. Nesse meio tempo o sr. Joshua Bloch deve ter se dado conta que seria interessante definir as coisas com interfaces e classes abstratas, não só com classes abstratas.
Heranças multiplas e ponteiros são as duas maiores questões. Ambas, se usadas bem, fazem milagres, mas geralmente só trazem problemas. No caso da herança multipla, pode-se herdar métodos comuns a duas classes totalmente diferentes entre sí, fazendo um override muito estranho! E é o compilador que escolhe que método será o pai. Que criterio ele usa? Varia de compilador pra compilador, mas geralmente é quem veio primeiro na lista das heranças! No fim das contas, nem o programador sabe que método veio de quem!
Já no caso das interfaces, como não tem nada instanciado, nada disso ocorre. Ainda que dois métodos retornem a mesma coisa, não há diferença entre eles. Se aceitarem argumentos diferentes, isso não é override, e sim polimorfismo, então, sem problemas!
Herança múltipla não é exatamente um bicho de sete cabeças… mas é que é meio complicado lidar com ela. A vida é meio curta para lidar com coisas que são complicadas e cuja razão para serem complicadas não é muito clara…
A linguagem Eiffel usa apenas herança múltipla, sem interfaces, mas as regras de herança são bem detalhadas e definidas. Um dos grandes problemas da herança múltipla é quando você tem o caso em losango (diamond):
> Classe2 ->
/ \
Classe1 < > Classe4
\ /
> Classe3 ->
(não sei se o diagrama ficou legal, de qualquer maneira não parece mesmo um losango…)
Quando um método da Classe1 é herdado pela Classe4, qual é o caminho da herança: através da Classe2 ou da Classe3? Isso deve ser explicitamente especificado em Eiffel, se não me engano (não estou com o manual da linguagem aqui.)
Pessoal tenho uma duvida relacionada.
Se eu tenho uma classe concreta estendida de uma classe abstrata, a classe concreta é obrigada a implementar todos os métodos da classe abstrata ou pode implementar só alguns metodos abstratos da classe abstrata???
[quote=sk2ck]Pessoal tenho uma duvida relacionada.
Se eu tenho uma classe concreta estendida de uma classe abstrata, a classe concreta é obrigada a implementar todos os métodos da classe abstrata ou pode implementar só alguns metodos abstratos da classe abstrata???[/quote]
Se é concreta ela é obrigada a implementar.
abstract class B{
public abstract void x();
public abstract void y();
}
public class A extends B {
public void x() {}
}
A.java:5: A is not abstract and does not override abstract method y() in B
public class A extends B {
^
1 error
A unica chance de não implementar alguma coisa é se ela for abstrata também.
abstract class B{
public abstract void x();
public abstract void y();
}
/* Agora vai compilar! */
public abstract class A extends B {
public void x() {}
}
[quote=sk2ck]Pessoal tenho uma duvida relacionada.
Se eu tenho uma classe concreta estendida de uma classe abstrata, a classe concreta é obrigada a implementar todos os métodos da classe abstrata ou pode implementar só alguns metodos abstratos da classe abstrata???[/quote]
Deve implementar todos os métodos definidos como abstract na classe abstrata.
Obrigado pessoal…
É chamado de O Losango Mortal e é um problema porque fica complexi demais (por causa das ambiguidades). Como fizeram o possível para o Java ser simples, isso não entra muito na linguagem. Na verdade, thingol, fica parecido com um losango. Posso complementar alguma coisa que você falou?
No Head First Java (o mais simprão, da Kathy e do Bert) eles mostram isso. Pense num diagrama de classes: DigitalRecord é superclasse e tem 2 subclasses: CDBurner e DVDBurner e ambos sbrescrevem o método burn() da DigitaRecord. Existe ainda uma outra classe, a ComboDrive, que extende tanto CDBurner quanto DVDBurner. O problema: que método burn() será executado quando eu chamar burn() em ComboDrive?
É o que você falou, mas em outras palavras
[quote=saoj]Vc só não falou do lance do InputStream.
Alguma idéia sobre o porque daquilo ??? Faz diferença no final das contas ???[/quote]
Sérgio, a API java.io é do jeito que é por causa do padrão Decorator.
Peguei a figura abaixo do livro de padrões de projeto da série Head First (capítulo que fala sobre o decorator):
Abraços
[quote=thingol]Gosto de explicar “interface” e “classe abstrata” através de um exemplo concreto.
Quando você vai à loja e compra uma TV com DVD incorporado, modelo Philips AD-1234, você está levando para casa um objeto que é uma instância da classe PhilipsAD1234.
Essa classe PhilipsAD1234 implementa as seguintes interfaces:
TV - contendo os métodos ligar(), visualizar(), etc.
DVD - contendo os métodos ligar(), reproduzirDisco(), etc.
Note que ambas as interfaces têm um método em comum (ligar), mas isso não ocasiona conflitos.
Ela é extensão de uma classe abstrata “PhilipsTV” que representaria todas as TVs Philips, que têm alguns componentes em comum (digamos a fonte chaveada, que é um “private member” dessa classe); mas você não consegue ir à loja e comprar uma instância da classe abstrata PhilipsTV; consegue apenas adquirir uma instância da classe PhilipsAD1234, PhilipsQR9876 etc.
Se você comprar uma TV modelo Sony XY-5678, você está levando para casa um objeto que é uma instância da classe SonyXY5678, que implementa a interface TV, tal como a TV Philips citada acima.
Mesmo que a TV Sony não tenha nenhum componente em comum com a TV Philips, nem por isso deixa de ser uma TV, já que implementa a interface TV.
Portanto:
- Classes abstratas definem uma implementação comum, mas parcial;
- Interfaces definem um padrão de funcionalidades a ser seguido.
É por isso que existem as duas coisas em Java, e elas são na verdade bem diferentes.
Dentro da medida do possível, prefira usar interfaces, elas são muito mais flexíveis que classes abstratas. Use as classes abstratas quando você necessita limitar a flexibilidade de propósito.[/quote]
Só para constar, achei muito boa essa definição… nada como uma analogia para esclarecer um assunto…
Como o saoj falou, muitas vezes definimos uma modelagem por feeling( CHICO XAVIER MODE ON :lol: ), mas ter essa definição na cabeça ajuda bastante…