Escolar Documentos
Profissional Documentos
Cultura Documentos
Java Basico Modulo 07
Java Basico Modulo 07
www.t2ti.com
1
www.t2ti.com
2
Mdulo
07
Introduo
Orientao a Objetos
Herana, Sobreescrita e Polimorfismo
Em relao ao paradigma Orientado a Objetos ns j vimos o que uma Classe, aprendemos tambm que um objeto nada mais do que a instanciao de uma classe e que um dos pilares da Orientao a Objetos o encapsulamento. Neste mdulo e no prximo ns iremos continuar nossos estudos relacionados aos conceitos fundamentais da programao Orientada a Objetos. A seguir estudaremos Herana, Sobreescrita e Polimorfismo.
Herana
No paradigma orientado a objetos podemos definir um conjunto de classes em uma estrutura hierrquica onde cada uma das classes herda caractersticas da suas superiores nesta estrutura. No mundo real temos que uma pessoa herda caractersticas de seus pais que herdaram de seus avs e assim por diante. Respeitando as limitaes das linguagens de programao, o que acontece quando utilizamos herana no nosso cdigo uma tentativa de implementar esta propriedade da natureza. Para ficar mais claros vamos partir para um exemplo. Imagine que estivssemos implementando um programa que fosse utilizado em um concessionria de veculos. Esta concessionria vende carros de passeio, jipes e veculos utilitrios. Para implementar as classes destes veculos poderamos criar trs classes distintas, A seguir a classe Jipe:
public class Jipe { private String marca; private Double capacidadeTanqueCombustivel; public Double getTanqueCombustivel() { return capacidadeTanqueCombustivel;
www.t2ti.com
3
www.t2ti.com
4
Perceba que, nas linhas destacadas em amarelo, temos as caractersticas que dizem respeito a apenas um dos tipos de veculos, isto , no nosso modelo, apenas jipes tm trao 4x4, somente os carros de passeio tm opo de ligar o ar condicionado e farol de milha uma caracterstica existente apenas nos veculos utilitrios Todas os demais estados e comportamentos voc ainda lembra o que so estado e comportamento de um objeto? so idnticos, na verdade para criar estas trs classes foi realizado uma simples cpia e cola dos membros que so iguais. Isto vlido, por enqanto, afinal de contas estas caractersticas permanecero idnticas para os trs tipos (Jipe, Carro de Passeio e Utilitrio). Agora vamos explorar um pouco mais o nosso modelo, a nossa concessionria vai comear a vender outros 5 tipos de veculos diferentes, cada um com suas peculiaridades, l vamos ns criar mais 5 classes e copiar e colar mais 5 vezes! E mais, o cliente do software identificou uma caracterstica importante dos veculos que deve ser adicionada ao modelo, o cdigo do chassi. L vamos ns de novo implementar mais 8 afinal so 5 novos veculos mais os 3 anteriores atributos com getter e setter para contemplar esta caracterstica. Na verdade nada disto seria necessrio se ns tivssemos utilizado corretamente o conceito de herana da programao Orientada a Objetos. Perceba que com exceo das caractersticas que esto grifadas em amarelo todas as demais
www.t2ti.com
5
Tudo o que era comum a todos os veculos foi concentrado na classe Veiculo. Para que as demais classes herdem estas caractersticas ns devemos utilizar a palavra reservada extends. As novas classes tm como superclasse a classe Veiculo:
public class Jipe extends Veiculo{ public void ligarTracao4x4() { //Cdigo aqui }
public class CarroPasseio extends Veiculo{ public void ligarArCondicionado() { //Cdigo aqui } } public class Utilitario extends Veiculo { public void ligarFarolMilha() { //Cdigo aqui }
www.t2ti.com
6
Nesta nova hierarquia de classes toda a subclasse de Veiculo ir compartilhar as suas caractersticas, dizemos que um jipe, carro de passeio ou utilitrio so todos do tipo Veiculo. E da mesma forma toda a subclasse de Jipe ir herdar as caractersticas tanto de Veiculo quanto de Jipe. O exemplo abaixo mostra como, apesar de no ser declarado o atributo especificamente na classe Jipe, posso acessar atravs do getter
capacidadeTanqueCombustivel:
Jipe jipe = new Jipe(); Double capacidadeTanqueJipe = jipe.getCapacidadeTanqueCombustivel(); jipe.setCapacidadeTanqueCombustivel(48.0);
Percebeu!? No exemplo acima estou manipulando o atributo atravs dos mtodos (getter e setter) sem t-los declarados explicitamente na classe Jipe pois, o compilador sabe que na verdade estou herdando estas caractersticas da classe Veiculo. Esta hierarquia de classes garante que todas as mudanas efetuadas na classe Veiculo se propagam para as suas subclasses. Por exemplo, se for solicitado adicionar o comportamento buzinar, e este comportamento for uma caractersticas que todos os veculos devem ter, ento basta adicion-lo a classe Veiculo que automaticamente todas as subclasses compartilharo a mesma funcionalidade. Abaixo temos o exemplo desta modificao na classe Veiculo:
www.t2ti.com
7
Desta forma ns evitamos aquele super-trabalho de copiar, colar e manter vrias classes cada vez que uma alterao solicitada, concentramos tudo o que possvel e pertinente na nossa classe Veiculo e realizamos a manuteno do cdigo em apenas um ponto da aplicao. Assim, a herana viabiliza o reuso do cdigo existente pois, como podemos perceber o cdigo da classe Veiculo reutilizado por todas as suas subclasses e, ainda mais, podemos ter uma hierarquia de herana de tamanho indefinido onde todas as subclasses iro sempre herdar caractersticas das superclasses at a raiz da estrutura hierrquica (classe do topo da hierarquia). Vamos brincar um pouco com o nosso modelo, imagine que fossmos vender o nosso software de gerncia de concessionrias para uma concessionria localizada em um pas que esteja em uma zona conflituosa e, alm destes veculos a concessionria vende tambm tanques de guerra - agora eu apelei! :) - portanto devemos adicionar a nossa hierarquia mais uma classe. A classe que representa um tanque de guerra fica da seguinte forma:
public class TanqueGuerra extends Veiculo { public void atirarMetralhadora() { //Cdigo aqui } public void atirarCanhao() { //Cdigo aqui } }
www.t2ti.com
8
E novamente eu sei que a minha classe TanqueGuerra tambm possui as caractersticas herdadas da classe Veiculo, ou seja, alm de atirar com a metralhadora e o canho caractersticas prprias deste tipo de veculo o nosso tanque de guerra poder buzinar, acelerar, frear e etc. Abaixo temos um exemplo do uso da classe TanqueGuerra:
TanqueGuerra osorio = new TanqueGuerra(); osorio.atirarCanhao();//derivado da classe TanqueGuerra osorio.buzinar();//derivado da classe Veiculo
Agora ns podemos pensar o seguinte, o som emitido pela buzina (Bmmmm) fica bem para um Jipe, Utilitrio e at quem sabe um Tanque de Guerra, mas nunca uma senhora de idade iria adquirir um carro de passeio com uma buzina deste tipo. Sendo assim ns precisamos modificar o som da buzina apenas para os carros de passeio de forma a deix-la mais condizente com a realidade do uso deste veculo. Para isto devemos conhecer mais um dos fundamentos da Orientao a Objetos a sobreescrita de mtodos.
Sobreescrita (override)
A sobreescrita de mtodos uma caracterstica que permite alterao do comportamento de uma superclasse pelas suas subclasses. Ao sobreescrevermos um mtodo ns estamos fornecendo uma nova implementao para o mesmo comportamento. Para exemplificar vamos alterar o comportamento da nossa buzina para que seja mais adeqada ao um carro de passeio. A classe Veiculo permanece do mesmo jeito, modificamos apenas a classe CarroPasseio conforme abaixo:
www.t2ti.com
9
public class CarroPasseio extends Veiculo{ public void ligarArCondicionado() { //Cdigo aqui } public void buzinar()//Estamos sobreescrevendo o mtodo buzinar() da superclasse Veiculo { System.out.println("Fon fon"); } }
CarroPasseio
Perceba que o som emitido pelo tanque de guerra continuou o mesmo, derivado da classe Veiculo, porm o som emitido pelo carro de passeio mudou, ou seja, alteramos o comportamento pr-definido para o mtodo buzinar(). Nesta situao o mtodo buzinar da classe Veiculo completamente ignorado e substitudo pelo da classe CarroPasseio, porm pode haver situao que seja interessante a manuteno da implementao existente com adio de implementao prpria. Para que isto seja possvel ns devemos, ao sobreescrever o mtodo, adicionar a palavra reservada super ao corpo do mtodo que estamos fornecendo nova implementao e invocar o mesmo mtodo da superclasse. No exemplo abaixo utilizamos a implementao do mtodo buzinar da superclasse e ao mesmo tempo adicionamos nova implementao:
public class TanqueGuerra extends Veiculo { public void atirarMetralhadora() { //Cdigo aqui } public void atirarCanhao() { //Cdigo aqui
www.t2ti.com
10
A palavra reservada super uma referncia a superclasse. Ao executarmos este mtodo a JVM ir primeiro invocar e executar o mtodo da superclasse para depois continuar a execuo local. Ao sobreescrevermos um mtodo o modificador de acesso neste caso
public
nunca pode ser mais restritivo do que o do mtodo que est sendo
sobreescrito, ou seja, no podemos alterar o modificador de acesso de forma que o mtodo tenha sua visibilidade reduzida, por exemplo, se tentarmos mudar a assinatura do mtodo buzinar, conforme abaixo, o compilador no ir permitir:
No entanto o inverso vlido, podemos aumentar a visibilidade de um mtodo, ou seja, se um mtodo for declarado
protected
e aumentarmos a
www.t2ti.com
11
public static void main(String[] args) { CarroPasseio carroMadame = new CarroPasseio(); carroMadame.buzinar(); carroMadame.buzinar("Fon! Fon!"); }
Observe
que
nosso
novo
mtodo
(grifado
em
amarelo)
est
sobrecarregando o mtodo j existente, na verdade temos dois mtodos buzinar, com e sem parmetros, respectivamente, o mtodo da classe CarroPasseio e o mtodo derivado (herdado) da classe Veiculo. A sobrecarga de mtodo cria um mtodo novo na classe mantendo o mtodo existente.
Polimorfismo
O polimorfismo, que significa muitas formas, permite que uma mesma referncia se comporte de formas diferentes. Utilizando corretamente o polimorfismo ns podemos fazer o cdigo ficar mais claro, genrico e, portanto, reutilizvel. Segue abaixo um exemplo:
public class MainModulo09 { /** * @param args */ public static void main(String[] args) { Veiculo veiculo = criarVeiculo(args[0]); veiculo.buzinar(); } public static Veiculo criarVeiculo(String tipo) { if(tipo == null) { return new CarroPasseio(); }else if(tipo.equals("utilitario")) { return new Utilitario(); }else if(tipo.equals("tanque")) { return new TanqueGuerra(); }else if(tipo.equals("passeio")) { return new CarroPasseio();
www.t2ti.com
12
A invocao do mtodo buzinar() na varivel veiculo feita de forma polimrfica, isto , pode possuir diversos comportamentos diferentes. O resultado desta invocao ser apenas conhecido em tempo de execuo pois, dependendo do parmetro de entrada do mtodo main o objeto retornado pelo mtodo criarVeiculo() ser de tipos diferentes. Perceba que a varivel veiculo do tipo Veiculo, ou seja, ela pode referenciar objetos das classes Jipe, CarroPasseio, TanqueGuerra e Utilitario, afinal, conforme visto, todas estas classes so tambm do tipo Veiculo (Herana). A JVM s conhecer a referncia da varivel veiculo em tempo de execuo, que ser dependente do parmetro de entrada do mtodo main, ou seja, a JVM at sabe que em tempo de execuo esta varivel ir referenciar um objeto do tipo Veiculo, ou uma de suas subclasses, porm ela no sabe qual dos tipos de Veiculo ser (Jipe, TanqueGuerra, Utilitario ou CarroPasseio). Durante a execuo da aplicao a JVM ir identificar qual tipo a varivel est referenciando e assim ir invocar a implementao do mtodo buzinar() adequada. Observe abaixo a execuo do cdigo:
www.t2ti.com
13
A situao acima identificada resulta em erro de compilao, isto acontece porque o mtodo ligarArCondicionado() no faz parte da classe Veiculo ou de uma de suas superclasses, ou seja, o compilador verifica se o mtodo existe em tempo de compilao. Desta forma, mesmo que voc tenha certeza que naquele momento a varivel far referncia um objeto do tipo CarroPasseio, o compilador no ir aceitar este tipo de construo. No entanto existem solues para isto, a primeira e mais simples substituir o tipo da varivel, conforme abaixo:
CarroPasseio veiculo = criarVeiculo(args[0]); veiculo.buzinar(); veiculo.ligarArCondicionado();
O K
A segunda forma executando um cast, a idia a mesma do cast de tipos primitivos porm, neste caso, ns avisamos ao compilador que a varivel faz referncia a uma das subclasses da hierarquia de classes, observe a construo abaixo:
Veiculo veiculo = criarVeiculo(args[0]); veiculo.buzinar(); ((CarroPasseio)veiculo).ligarArCondicionado();
Podemos dizer que o compilador entende algo como: Opa?! Beleza! Se voc est garantindo que eu vou encontrar um CarroPasseio neste endereo ento eu deixo voc invocar este mtodo porm espero que saiba o que est fazendo pois se, em tempo de execuo, a referncia for de outro tipo a JVM ir emitir uma exceo bem espalhafatosa.
K O
www.t2ti.com
14
Conforme dito anteriormente, ao adicionar o modificador final a declarao da classe estou inviabilizando qualquer tipo de estenso por outras classes, isto , apesar da classe Jipe estender a classe Veiculo, nenhuma outra classe poder estender, ser subclasse, da classe Jipe. Em mtodos a aplicao deste modificador feita da seguinte forma:
public
class Jipe extends Veiculo{ public void ligarTracao4x4() { //Cdigo aqui } public final void buzinar() { System.out.println("Buzina jipe"); }
Agora a classe Jipe pode ser estendida porm qualquer uma de suas subclasses no poder sobreescrever o mtodo buzinar(). Isto interessante quando desejamos que determinado comportamento no seja alterado em hiptese nenhuma. Nos pacotes bsicos da linguagem Java existem diversas classes que so modificadas pelo final, temos como exemplo a classe String e a classe Math.
www.t2ti.com
15
Classe Object
Para encerrar este mdulo vejamos a classe Object. Em Java todas as classes, eu disse todas as classes! String, Math, as minhas classes, as suas classes e etc. estendem a classe Object e portanto so do tipo Object tambm. Desta forma mesmo quando declaramos uma classe conforme abaixo:
public class Classe { }
Por isso todos os objetos objetos e no tipos primitivos! sempre iro passar (true) por um teste conforme abaixo:
www.t2ti.com
16
L-se: Todo objeto instncia da classe Object. A seguir temos os alguns dos principais mtodos da classe Object:
Mtodo
equals() toString() hashCode()
Descrio
Indica quando um objeto igual a este Retorna a representao textual deste objeto Retorna o cdigo hash para este objeto
Todos estes mtodos podem ser sobreescritos, e muitas vezes o so, os mtodos equals() e hashCode sero abordados no mdulo de Colees. Abaixo temos um exemplo da utilizao do mtodo toString():
public class Jipe extends Veiculo{ public void ligarTracao4x4() { //Cdigo aqui } public final void buzinar() { System.out.println("Buzina jipe"); } public String toString() { return "toString do Jipe"; } }
Observe que o mtodo toString(), da classe Object, est sendo sobreescrito pela minha classe Jipe, a seguir temos trecho de cdigo que imprime um objeto do tipo Jipe:
Veiculo veiculo = new Jipe(); System.out.println(veiculo);
Quando imprimimos um objeto, a JVM invoca o mtodo toString() do objeto, se este mtodo no foi sobreescrito ento o mtodo toString() invocado o da
www.t2ti.com
17
O que uma representao textual significativa do objeto para a JVM, mas no para ns seres humanos :).
EXERCCIOS
Aprenda com quem tambm est aprendendo, veja e compartilhe as suas respostas no nosso Frum: Exerccios Mdulo 07 Herana, Sobreescrita e Polimorfismo 1 Crie uma hierarquia de classes conforme abaixo com os seguintes atributos e comportamentos (observe a tabela), utilize os seus conhecimentos e distribua as caractersticas de forma que tudo o que for comum a todos os animais fique na classe Animal:
Cachorro
Possui Nome Possui Idade Deve emitir som Deve correr
Cavalo
Possui Nome Possui Idade Deve emitir som Deve correr
Preguica
Possui Nome Possui Idade Deve emitir som Deve subir em rvores
2 Implemente um programa que crie os 3 tipos de animais definidos no exerccio anterior e invoque o mtodo que emite o som de cada um de forma polimrfica, isto , independente do tipo de animal.
www.t2ti.com
18
www.t2ti.com
19
www.t2ti.com
20