Entendendo a hierarquia de classes (extends, implements)  XML
Índice dos Fóruns » Java Avançado
Autor Mensagem
brunocia2000
Thread.start()
[Avatar]

Membro desde: 27/03/2006 21:14:18
Mensagens: 32
Offline

Olá pessoal, resolvi escrever um tutorial para quem ainda tem duvidas sobre a hierarquia de classes em java, e gostaria de agradecer ao pessoal que tem me ajudado muito nos meus projetos, principalmente o Vini-Godoy!!!

Bom, começando...

Uma hierarquia de classes, explicando melhor é um framework, ou seja um sistema mais complexo que uma simples classe, onde cada classe tem seus métodos, e variaveis, e principalmente sua função sobre o sistema.

No meu caso, eu estou criando um jogo de shooter vertical, em java e meu framework se encontra da seguinte maneira:



Como podem notar, a minha hierarquia está gigante, eu poderia fazer o jogo todo em uma só classe, porém o unico problema de fazer em uma unica classe, colocando todos seus metodos nela, é de "morrer afogado no próprio codigo", ou seja, se perder dentro do seu codigo, no meu caso estou criando uma Engine, ou seja, um projeto de jogo, onde eu poderei alterar futuramente o codigo, e alguns graficos, para criar a versão 2, e 3, e 4, etc, do jogo, podendo até mesmo criar outros jogos já que é um projeto bem organizado em classes.

Cada classe tem sua função:

nave -> Classe principal do jogo, que se encarrega de chamar os metodos correspondentes em outras classes.

Graficos -> Contém os métodos de pintura do jogo, nele estão o paint(), update(), e métodos de desenhar componentes do jogo.

GameStatus -> A thread principal chama o metodo gameStatus() de dentro dessa classe, para obter as ações atuais do jogo. Se a variavel game_status for igual a 0, carrega as imagens, se for igual a 1 exiba tela de entrada, etc.

Teclado -> Contém as ações do teclado, ou seja, se pressionar o botão <space> faça isso, se pressionar o botao <seta esquerda> faça aquilo.

Variaveis -> Contém todas as variaveis, e seus metodos de inicialização para o sistema todo, além de herdar as funções da classe Applet, que contém os métodos essenciais para um applet java rodar, nesse caso, Variaveis é a super classe do projeto, e suas subclasses desde a classe nave obtém de forma indireta as propriedades da classe Applet, esse é o espírito da coisa.

Resumindo tudo, para fazer uma classe obter de forma direta acesso aos seus métodos e variaveis, usamos a palavra chave extends:

public class Classe1
{
int x = 200;
}
public class Classe2 extends Classe1
{
exiba (x);
}


Nesse caso, a Classe2 herda todos os métodos e variaveis da Classe1, podendo exibir a variavel x e recebendo o valor 200.

Caso na Classe2 existir também uma variavel x, por padrão ela será exibida, pois o java busca o x primeiro na classe atual, caso nao encontrar, irá checar as classes que ele herda os métodos, mas se caso isso acontecer, e você quer exibir o valor x da super classe Classe1, deverá usar a palavra chave super:

exiba (super.x);

ou para algum método é o mesmo caso, super.metodo1();

** A palavra chave implements...

A palavra chave implements serve para uma classe implementar uma interface, o que é uma interface? Uma interface é uma classe normal porém com seus métodos sem corpo, ela define um padrão de trabalho, para uma outra classe ver e implementar.

Por exemplo:



[/code]

Nesse caso temos uma classe Webmaster, que implementa a interface Etapasweb, uma interface como dito anteriormente é um conjunto de dados, assim como uma classe, porém essa define um padrão de comportamento a ser seguido rigidamente por uma outra classe. Se a classe Webmaster nao implementasse algum método da interface Etapasweb, geraria um erro na hora de compilar, isso se dá por causa da palavra chave implements.

Ao declarar implements Etapasweb voce disse que a classe Webmaster teria seus métodos implementados, então nesse caso a classe Etapasweb define como Webmaster tem que trabalhar, se voce é um webmaster e não hospeda o site por exemplo, nao estará seguindo o padrão de um webmaster, ou até se nao hospedar o site! rsrss

A interface Runnable por exemplo, se voce implementa ela, deve obrigatoriamente implementar o corpo do método run(), porém isso ja entra em outra história (Threads).

Então é isso pessoal, espero que todos tenham entendido a importância de usar multiplas classes, e interfaces em um sistema complexo (framework).

Abraços

Ta sem nada pra fazer na Internet? Entra aí! http://www.clica.net

Webdesigners, me ajudem na campanha: http://www.clica.net/sites-gratis
[Email] [WWW] [MSN]
bzy
JavaGuru
[Avatar]

Membro desde: 23/08/2006 19:34:00
Mensagens: 215
Localização: São Paulo - Guarulhos
Offline

Cara! Interface é só isso mesmo? Métodos sem corpo? É a primeira vez que vejo um exemplo é a primeira vez que entendo !

SCJP - Sun Certified Java Programmer
http://meumundojava.blogspot.com/
Memento mori.
[WWW] [ICQ]
Ehb
JavaChild

Membro desde: 05/06/2006 04:54:18
Mensagens: 106
Offline

Sera que podia me informar quando acabasse o projecto ? Gostaria de saber como ficou.

Agradecido
[Email]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

Na hora de implementar, a interface é só isso mesmo. Uma "classe" cheia de métodos sem corpo, que pode ser "herdada" (na verdade, implementada) por qualquer um.

Mas a definição de interface é um pouco mais abrangente.

A interface representa um compromisso. Mais importante que os métodos, é o javadoc desses métodos! Ou seja, o contrato da interface.

O que eu quero dizer com isso? Eu entrego para você uma interface dizendo, "implemente esse, esse e esse métodos, dessa forma, e eu te forneço determinado serviço".

Vamos fazer um exemplo bem simples. Vamos supor que você gostaria de uma classe que, dado um componente qualquer, imprimisse o nome dele, a altura e a largura. Essa classe você vai distribuir para terceiros, na sua framework. Então, você não sabe como o pessoal vai implementar esses componentes, se em swing, ou em swt.

Entretanto, o que você sabe? Que os componentes tem que ter um nome, uma altura e uma largura, certo? Para isso você modela uma interface:



Pronto! Agora você pode fazer a sua classe que imprime:

Note que agora, sua classe ImpressoraDeComponente, pode funcionar com qualquer componente, seja Swing, AWT, SWT ou um criado por alguém que você ainda nem conhece. Basta que essa pessoa implemente a interface ComponenteImprimivel e, mais importante, retorne exatamente o que o seu contrato (javadoc) pede.
[WWW]
bzy
JavaGuru
[Avatar]

Membro desde: 23/08/2006 19:34:00
Mensagens: 215
Localização: São Paulo - Guarulhos
Offline

To começando a entender, é como se fosse um "mapa" dos métodos que tenho

SCJP - Sun Certified Java Programmer
http://meumundojava.blogspot.com/
Memento mori.
[WWW] [ICQ]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

Só melhorando um pouco os termos.

Um framework não é sinônimo de uma aplicação complexa (embora muitos frameworks sejam, efetivamente, complexos).

Framework é um conjunto de bibliotecas ou classes que são usados para implementar uma estrutura padrão de uma aplicação. Normalmente, os frameworks se dedicam a facilitar uma tarefa específica.

A linguagem java seria muito pobre sem suas diversas frameworks. Por exemplo, o Swing é uma framework que te auxilia na construção de interfaces gráficas. A Collections Framework te fornece uma série de classes (List, Set, Hash, Queue) para lidar com coleções de objetos.

Existem também frameworks de terceiros. O Hibernate auxilia na tarefa de salvar objetos no banco de dados. O JMonkeyEngine auxilina na criação de jogos de computadores.

Alguns autores diferenciam Framework de Toolkit. Para eles, Framework é um conjunto de classes extensível, enquanto o Toolkit seria apenas um conjunto de classes interessantes, mas não feitas com a idéia de herança em mente. Nesse caso, o Swing seria uma framework, enquanto o HttpUnit, não.
[WWW]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

Um mapa sim, mas não dos objetos que você tem, mas do que precisa ter para trabalhar.

Você diz para um terceiro.
"Eu tenho um framework que te ajuda nisso, nisso e naquilo".

E o terceiro diz,
"ok, mas o que eu tenho que fazer para usar essa maravilha?"

Você responde:
"Simples, implemente esse conjunto de interfaces".

Isso porque, a sua aplicação espera que quem implementou as interfaces que você produziu respeitem o contrato.

Veja o exemplo. Você poderia estar fazendo um programa gráfico, que pintasse objetos. Mas para isso, você precisaria de objetos coloridos, certo? Qual é a maneira mais simples de dizer "Ei, pessoal, eu preciso de objetos coloridos"?

A maneira mais fácil é essa:


Pronto, agora, todos que quiserem usar sua classe de pintura, se deparão com um método do tipo:
pintarObjeto(Colorivel obj);

Quando você implementou o método pintar, você não se preocupou em como o objeto colorido foi implementado. Você apenas se preocupou com o fato de que ele era colorido, e tinha métodos que você precisava, com o comportamento que você esperava...

Se num jogo alguém quiser usar sua framework, poderia fazer:

public class Nave implements Colorivel

Agora, se alguém está fazendo uma aplicação de um livro infantil, e ainda sim quer usar sua framework faria:
public class CoelhoFofinho implements Colorivel

Na hora que você montou o método pintarObjeto, você não estava preocupado em saber quem exatamente seria o Colorivel. Para você tudo estaria bem, desde que fosse um Colorivel qualquer. É isso que a interface mostra. Ela diz que "Para meus métodos de pintura, um objeto colorido é alguém que tem o método getCor(), que retorna uma cor ou nulo, se o objeto for transparente".
[WWW]
Reilander
JavaChild
[Avatar]

Membro desde: 27/01/2007 21:28:37
Mensagens: 142
Localização: Feira de Santana - BA
Offline

Cara, você está explicando muito bem, mas ainda não entendi bem a real utilidade de se usar uma interface. Se ela apenas define métodos que, quem herdá-la (a classe), terá de implementá-los, não iria ser a mesma coisa de eu criar a minha classe e implementá-lo do mesmo jeito?

O que eu não consigo entender é o porquê de utilizá-la, não encontro uma razão óbvia. Toda a implentação do método vai estar na sua classe principal. De que me vale adquirir um "contrato", como muitos dizem, que no final das contas o "grosso" do método quem irá fazer sou eu?

É diferente, por exemplo, de herança, que você apenas acrescenta às funcionalidades da super classe, e ela já lhe fornece muitos serviços prontos. A interface não me fornece nenhum serviço. Apenas me restringe ao que eu tenho de implementar.

Realmente, isso ainda está difícil de abstrair...

"Por mais sujo que esteja o meu passado, meu futuro está intacto..."
[Email] [MSN]
brunocia2000
Thread.start()
[Avatar]

Membro desde: 27/03/2006 21:14:18
Mensagens: 32
Offline

Oi Vinicius, então no caso o framework que eu quis dizer é meu conjunto de métodos e interfaces que já segue um padrão para criar o jogo da nave, ou seja, um projeto mais complexo que um applet normal, porém que pode ser reutilizavel.

Ehb

--------------------------------------------------------------------------------

Sera que podia me informar quando acabasse o projecto ? Gostaria de saber como ficou.

Agradecido


Ehb, eu acho que vai demorar um pouquinho, pois ando muito ocupado com outras coisas e não tive muito tempo pra mandar bala no programa, mas assim que o jogo ficar pronto eu posto aqui no GUJ o link para jogar online.



bzy
--------------------------------------------------------------------------------

Cara! Interface é só isso mesmo? Métodos sem corpo? É a primeira vez que vejo um exemplo é a primeira vez que entendo !


Bzy, interface é apenas isso mesmo, porém o diferencial de uma interface não é seus métodos sem corpo, e sim o padrão que ela manda uma classe seguir, é como se ela fosse o patrão, e te dá 3 tarefas:



Se a classe Funcionario implementar a Interface Patrao, ela deverá implementar por obrigação todos seus métodos, é o mesmo que se voce entrar numa empresa, terá que fazer todos as etapas que seu patrão te passar, nesse caso o Patrao é a interface, se caso algum método da interface nao for implementado gera erro de compilação.

****

Outra coisa que notei que bastante gente tem duvida, é sobre a palavra chave super com multiplas classes. Exemplo:



Certo pessoal

Abraços

Ta sem nada pra fazer na Internet? Entra aí! http://www.clica.net

Webdesigners, me ajudem na campanha: http://www.clica.net/sites-gratis
[Email] [WWW] [MSN]
brunocia2000
Thread.start()
[Avatar]

Membro desde: 27/03/2006 21:14:18
Mensagens: 32
Offline

Reilander
--------------------------------------------------------------------------------

Cara, você está explicando muito bem, mas ainda não entendi bem a real utilidade de se usar uma interface. Se ela apenas define métodos que, quem herdá-la (a classe), terá de implementá-los, não iria ser a mesma coisa de eu criar a minha classe e implementá-lo do mesmo jeito?

O que eu não consigo entender é o porquê de utilizá-la, não encontro uma razão óbvia. Toda a implentação do método vai estar na sua classe principal. De que me vale adquirir um "contrato", como muitos dizem, que no final das contas o "grosso" do método quem irá fazer sou eu?

É diferente, por exemplo, de herança, que você apenas acrescenta às funcionalidades da super classe, e ela já lhe fornece muitos serviços prontos. A interface não me fornece nenhum serviço. Apenas me restringe ao que eu tenho de implementar.

Realmente, isso ainda está difícil de abstrair...


Reilander, eu também penso assim, por isso que meu projeto tem mais classes do que interface, e mais extends do que implements.

Porém é interessante saber que as interfaces possuem um papel ótimo também para definir um padrão de trabalho totalmente organizado.

Mas explicando aqui uma interface que tenho no meu jogo, que é a interface LoopSteps, e a classe MainLoop...

MainLoop cria uma instancia da interface dessa maneira:

private LoopSteps game;

E invoca seus métodos:

game.processLogics(); // processa todas as funções do jogo
game.paintScreen(); // pinta na tela do jogo
game.renderGraphics(); // prepara o buffer para ser desenhado


Só que dentro da interface esses métodos se encontram da seguinte maneira:

void processLogics();
void paintScreen();
void renderGraphics();

Lembrando que a classe MainLoop apenas cria a instancia game da interface LoopSteps, e na hora certa chama seus métodos, porém o que será executado?????? Nada!!! E se eu implementar a interface LoopSteps? O que será executado??? Os métodos implementados !!!!!

Observe que ai, MainLoop é uma classe que foi feita pra trabalhar com qualquer outra classe, sem precisar conhecer o nome de tal classe, apenas utilizando o padrão da interface LoopSteps, é possivel trabalhar com MainLoop.

Em outros detalhes, MainLoop é o presidente, LoopSteps é o diretor, sua classe que implementa LoopSteps é o funcionario.

MainLoop vai requisitar as tarefas a quem? Ao funcionario direto ou ao diretor? Ao diretor é claro.

E o diretor irá passar as tarefas requisitadas, a quem se contratar para o emprego, por exemplo:



Entendeu? Isso tudo define já um padrão a ser seguido, só que este caso é mais complexo, porém muito mais util!


Entendeu? Qualquer duvida postem ai!!!

Abraços

Ta sem nada pra fazer na Internet? Entra aí! http://www.clica.net

Webdesigners, me ajudem na campanha: http://www.clica.net/sites-gratis
[Email] [WWW] [MSN]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

Reilander,

Entenda o seguinte.

1. Você pode usar interfaces para definir contratos para classes que a implementação não será você quem vai fazer. Na verdade, você não tem nem idéia do que a pessoa que irá implementa-las vai fazer. Foi o caso da Nave e do CoelhoFofinho, no exemplo que passei. Quem implementou essas classes foram os clientes. Por isso, o cliente (no caso, outros programadores), devem ser restringidos pela interface, sem que sejam restringidos na hierarquia de classes que eles quiserem montar.

Veja por exemplo a interface ActionListener, do Swing. As pessoas que implementaram o Swing não sabiam que tipo de ação seria implementada, ou que classe implementaria a ação. Apenas sabiam que os usuários do swing esperavam que algum método fosse chamado quando actionPerformed fosse evocado.

2. Você pode usar interfaces para prover serviços para hierarquia de classes diferentes. Por exemplo, suponha que você tem a classe Carro, e a classe Cachorro. Ambos são coloridos, mas pertencem a hierarquias completamente diferentes. Portanto, você poderia usar o método de pintura que eu sugeri no exemplo acima, desde que ambas implementassem Colorivel.

3. O acoplamento do código é muito menor quando se usa interfaces do que quando se usa classes. Você passa a depender do serviço que a interface presta, não da implementação desse serviço. Veja por exemplo o caso do List. A interface List define uma lista de objetos, certo? Então eu posso dizer que o método abaixo funciona tanto para um ArrayList, quanto para um LinkedList, simplesmente recebendo um List como parâmetro:



Note que, quando implementei o método, não estou preocupado em qual implementação específica de lista estou usando, desde que, a classe em questão siga à risca o contrato da interface List, que representa uma lista. Eu poderia até mesmo implementar uma classe Baralho, que se comportasse com uma lista (e que não tivesse absolutamente nada a ver com as classes do Java) mas, se essa classe implementasse a interface List, esse método continuaria funcionando.
[WWW]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

Uma dica.

Leiam essas entrevistas (em inglês) com o Erich Gamma, criador do JUnit, Eclipse e um dos autores do livro Design Patterns.

http://www.artima.com/lejava/articles/designprinciples.html
http://www.artima.com/lejava/articles/reuse.html

Nessas entrevistas, ele explica porque é importante projetar sistemas usando interfaces, e não classes concretas. E também fala um pouco sobre frameworks, toolkits e aplicações reutilizáveis.

São um pouco longas, mas valem muito à pena!
[WWW]
Reilander
JavaChild
[Avatar]

Membro desde: 27/01/2007 21:28:37
Mensagens: 142
Localização: Feira de Santana - BA
Offline

Hum... se eu eu entendi bem, interfaces são úteis mais para padronização que para implementação. O que digo é, ao invés de cada classe, como no seu exemplo, usar um método peculiar de impressão, você tem certeza de que, se ela implementar a interface LoopSteps, ela terá um método paintScreen(). Bom, se eu criasse uma classe abstrata com todos esses três métodos abstratos o efeito seria o mesmo se eu a herdasse, não é? Mas digamos que, implementando uma interface, o código fica mais "elegante" e padornizado.

Agora, uma outra coisa que eu não entendi. Em um exemplo, você instanciou uma classe abstrata. Isso realmente é possível, ou você o fez apenas pra efeitos didáticos, facilitando sua explicação? Porque, se me lembro bem, como os métodos não são implementados, as interfaces não podem ser instanciadas. Mesmo que haja objetos criados e que os implementam, quando eu invocasse um de seus métodos, qual o método que ele invocaria, realmente? Bem, fica aí a dúvida.

Outra coisa: cara, valeu mesmo pelo teu esforço aí em explicar essas coisas. Este fórum do GUJ é fora de série. Gosto muito dele por causa de pessoas como tu - ViniGodoy. Estás ajudando muito, brother!

"Por mais sujo que esteja o meu passado, meu futuro está intacto..."
[Email] [MSN]
ViniGodoy
Moderador
[Avatar]

Membro desde: 11/12/2006 08:22:01
Mensagens: 20580
Localização: Curitiba/PR
Offline

Isso, padronização é um dos casos.

O problema das classes abstratas é que cada classe pode extender somente uma superclasse. Agora, voltemos ao exemplo do Colorivel.

Tanto Carro (que é filho de Automóvel, que é filho de Object) e
Cachorro (que é filho de Animal, que é filho de Object) gostariam de usar dos serviços do método pintarObjeto, que precisa de um Colorivel.

Vamos agora supor que Colorivel não é uma interface e sim uma classe e ver que problemas teremos:
1. Colorivel teria que ser pai de Animal, não de Cachorro. Afinal, Cachorro não pode extender ao mesmo tempo Animal e Colorivel;

2. Da mesma forma, Colorivel teria que ser pai de Automóvel. Veja que não só temos o problema 1 novamente, como agora criamos um relacionamento entre Animal e Automóvel (já que ambos são filhos da mesma superclasse);

3. Agora vamos supor que tivessemos diversos serviços como imprimirObjeto. Além de Colorivel, tivessemos super classes para ObjetoComTextura, Objeto3D, etc... Como ficaria a hierarquia de classes? Esse problema é especialmente ruim se apenas parte das classes de sua hierarquia é em 3D, outra parte tem textura e outra parte é colorida. Tente imaginar, usando superclasses, um diagrama dos filhos de animal, onde Cachorro e Gatos são coloridos, Gatos e Patos tem textura e Cachorros e Patos são em 3D.
Lembre-se, você quer separar a classe de pintura em:


Pense um pouco nesses problemas... espero que daí você entenda a necessidade das interfaces.

A propósito, você falou que uma classe abstrata foi instanciada num dos exemplos. Em qual exemplo foi e que classe foi essa? Nem classes abstratas e nem interfaces podem ser instanciadas.

Mas você pode usar uma interface ou classe abstrata para referenciar uma instância da filha. Por exemplo:

Colorivel objeto = new Cachorro();

O método objeto.getCor() vai mostrar a cor do cachorro.
[WWW]
bzy
JavaGuru
[Avatar]

Membro desde: 23/08/2006 19:34:00
Mensagens: 215
Localização: São Paulo - Guarulhos
Offline

Tanta coisa que vou ter que ler novamente com calma .
Mas pelo que entendo, tem coisas que são obrigatórias-obrigatória e coisas obrigatórias-úteis.
Oque seria as coisas obrigatórias-obrigatória > Seria a programação normal que não fucniona de outra maneira....
E as
obrigatórias-úteis > seriam como os comentários, as interfaces e até os privates, public e etc. São obrigatórios porque ajudam, mas pode fazer um programa inteiro sem nenhum comentário (e coitado de quem vier depois) como pode se fazer o contrário. Acho que a Interface é um desses casos. Mas eu acho que só irei entender mesmo quando usar em algum projeto meus, espero poder compartilhar e contar com vocês

Valeu pessoal.

SCJP - Sun Certified Java Programmer
http://meumundojava.blogspot.com/
Memento mori.
[WWW] [ICQ]
 
Índice dos Fóruns » Java Avançado
Ir para:   
Powered by JForum 2.1.8 © JForum Team