Professional Documents
Culture Documents
www.t2ti.com
1
www.t2ti.com
2
www.t2ti.com
3
Mdulo
08
Introduo
Estamos alcanando o fim da nossa trilha que apenas o incio do maravilhoso mundo que Java nos oferece e este momento bastante adeqado para introduzirmos os conceitos de classes Abstratas, Interfaces e Excees. Classes Abstratas e Interfaces so estruturas muito importantes quando programamos Orientado a Objetos com Java e, visto que j conhecemos os demais fundamentos da linguagem (reuso, herana, polimorfismo, encapsulamento, mtodos, etc.), est na hora de aplicarmos estes recursos existentes na linguagem. Uma das diferenas mais evidentes entre um bom e um mal programa o tratamento de excees, isto , a capacidade que o seu programa tem de responder a situaes inesperadas. Quando o tratamento de excees feito adeqadamente o seu programa fica mais robusto e ao mesmo tempo a usabilidade usabilidade nada mais do que a facilidade que um usurio tem em utilizar o programa aumenta sensivelmente. Porm antes de iniciarmos o novo contedo vamos conhecer uma importante caracterstica do construtor com parmetros levando em conta o uso de herana.
Herana - continuao
Ns j vimos que uma classe herda de sua classe pai as suas caractersticas porm a subclasse no herda o construtor, isto , o construtor individual para cada classe. Sempre que o construtor de uma classe invocado ele invoca , quando no explicitado, implicitamente o construtor da superclasse. Desta forma o construtor da
www.t2ti.com
4
acontece de forma automtica, ns no precisamos nos preocupar. O construtor default adicionado pelo compilador quando no h construtor declarado explicitamente, isto , se o programador no declarar um construtor o compilador ir adicionar, implicitamente, um pblico e sem parmetros. No entanto se for adicionado explicitamente um construtor o compilador no ir adicionar implicitamente o construtor default, o que significa que se ns criarmos um construtor com parmetros e estendermos a classe, obrigatoriamente teremos que, explicitamente, invocar o construtor da superclasse passando os parmetros. Para ficar mais claro vamos estender a classe Veiculo que possui um construtor com parmetros:
public class Jipe extends Veiculo{ public Jipe() { } //Demais membros...
www.t2ti.com
5
Perceba que no construtor da classe Jipe estamos invocando o construtor da classe Veiculo e passando uma String ("Marca padro de jipe"), ou seja, todas as instncias desta classe Jipe possuiro a mesma marca. Outra soluo seria a implementao de um construtor na classe Jipe que receba o mesmo parmetro repassando-o para a superclasse:
Construtor com parmetro
public class Jipe extends Veiculo{ public Jipe(String marca) { super(marca); } //Demais membros...
Desta forma mantida a lgica implementada pela superclasse. E por fim, uma terceira abordagem seria a mais de um construtor, observe que neste caso os dois construtores desenvolvidos anteriormente foram mantidos:
public class Jipe extends Veiculo{ private String modelo; public Jipe(){ super("Marca padro de jipe"); } public Jipe(String marca) { super(marca); } public Jipe(String marca, String modelo) { super(marca); this.modelo = modelo; } //Demais membros...
www.t2ti.com
6
Classes Abstratas
At este momento todas as classes que havamos desenvolvido eram classes concretas, isto todas as nossas classes podem originar objetos. Classes concretas so estruturas definidas e prontas para instanciarem objetos. Uma classe abstrata se comporta de forma diferente de uma classe concreta. Uma classe abstrata nunca pode ser instanciada de forma direta, seu maior propsito, a razo da sua existncia, ser estendida. Para que serve esta classe ento? Imagine a seguinte situao, ns temos uma hierarquia de classe conforme abaixo:
Todos os animais (cachorro, cavalo e preguia) estendem da classe Animal, no entanto, no nosso, programa a classe Animal por si s no representa nenhum tipo de animal. Isto , esta classe representa apenas um animal genrico e ela existe apenas para ser estendida dando origem a um animal de fato. Nesta situao mais adeqado que seja feita a mudana na classe Animal a fim de torn-la abstrata e inviabilizar a sua instanciao por qualquer parte do programa. Isto realizado adicionando-se o modificador abstract conforme abaixo:
public abstract class Animal { //corpo da classe }
Observe que agora a classe Animal no pode ser instanciada indevidamente em nenhum trecho do nosso programa, o exemplo abaixo ir produzir um erro de
www.t2ti.com
7
Desta forma ns temos certeza que durante a execuo do programa nunca haver um objeto da classe Animal e sim, sempre, de uma de suas subclasses. Uma classe abstrata pode possuir mtodos concretos um mtodo concreto todo aquele possui corpo veja o exemplo abaixo:
public abstract class Animal { private String nome; //getters e setters...
Mtodo concreto
cada uma das subclasses da classe Animal a fim de que forneam um comportamento adeqado pois, cada tipo de animal emite um som diferente dos demais. Porm, da forma como foi feito, esta condio no garantida pois, podemos ter uma subclasse da classe Animal que no sobreescreve o mtodo emitir som, no entanto existem formas de forarmos esta condio. Ao modificarmos o mtodo com abstract impedimos que alguma das subclasses no implementem o
Mtodo abstrato
Agora todas as subclasses da classe Animal iro obrigatoriamente ter que fornecer uma implementao para o mtodo emitirSom(). Alm da palavra reservada
abstract devemos encerrar o mtodo sem as chaves para que seja um mtodo
abstrato vlido. Uma classe abstrata pode conter apenas mtodos abstratos, concretos ou ambos. No entanto a presena de um mtodo abstrato torna, obrigatoriamente, a classe abstrata tambm.
www.t2ti.com
8
public class Cachorro extends Animal { public void emitirSom() { System.out.println("au! au!"); } }
Em Java no existe o conceito de herana mltipla, isto , cada classe pode estender (extends) apenas uma superclasse de cada vez. Por exemplo, a seguinte situao no permitida:
public class Cachorro extends Animal, Mamifero {
No entanto podemos ter hierarquia de classes de qualquer tamanho o que viabilizaria a extenso de diversas classes nesta estrutura.
Interfaces
Pense em uma interface como sendo uma classe totalmente abstrata, isto que no possui mtodos concretos. Desta forma, quando uma classe implementa uma interface ela obrigatoriamente deve implementar o conjunto de mtodos definidos pela interface. Do site da SUN, implementar uma interface permite a uma classe tornarse mais formal em relao ao comportamento que ela promete fornecer. Interfaces formam um contrato entre a classe e o mundo exterior, e este contrato garantido em tempo de compilao pelo compilador. Se a sua classe deseja implementar uma interface, todos os mtodos definidos pela interface devem aparecer no corpo antes da sua classe ser compilada. Em sntese, quando uma classe concreta implementa uma interface ela est garantindo que possui os mtodos especificados bem como a implementao destes, mesmo que o corpo do mtodo seja vazio. Aqui cabe uma observao: O uso de interfaces garante a existncia do comportamento porm no garante a sua correta implementao. Da mesma forma que classes, a definio de uma interface cria um novo
www.t2ti.com
9
Neste programa ns temos um mtodo que efetua a limpeza de qualquer objeto, seja ele um animal ou uma bola, porm caso o objeto seja de um dos dois tipos, Bola ou Animal, estes devero emitir seus sons caractersticos. Esta situao no pode ser resolvida atravs do uso de herana j que a classe Bola e a classe Animal no esto na mesma hierarquia de classes na verdade at poderia ser resolvida com herana e sobreescrita, mas havemos de convir que colocar a classe Bola e a classe Animal na mesma hierarquia um erro de projeto logo, a soluo seria a criao da interface EmiteSom conforme abaixo:
public abstract interface EmiteSom { } public abstract void emitirSom();
Observe que o uso do abstract opcional tanto na classe quanto no mtodo pois toda interface obrigatoriamente abstrata e seus mtodos tambm o so. A classe Animal e a classe Bola ficariam da seguinte forma:
public class Bola implements EmiteSom{
www.t2ti.com
10
public abstract class Animal implements EmiteSom{ private String nome; } //getters e setters...
Cad a implementao?
Perceba o uso da palavra reservada implements que informa ao compilador que esta classe est implementando uma interface. A classe Animal no fornece uma implementao para o mtodo emitirSom(), ao contrrio da classe Bola, isto acontece porque a classe Animal do tipo abstract. Quando uma classe abstrata implementa uma interface ela pode ou no fornecer a implementao dos mtodos oriundos da interface. Caso a classe abstrata no fornea a implementao destes mtodos (situao existente na classe Animal), obrigatoriamente cada subclasse concreta da classe abstrata ir ter que fornecer a implementao. Por exemplo, a classe Cachorro fica da seguinte forma:
public class Cachorro extends Animal { public void emitirSom() { System.out.println("au! au!"); } }
Implementao do mtodo
implementa a interface EmiteSom, mas deixou a responsabilidade pela implementao do mtodo para a classe concreta Cachorro. E agora o nosso mesmo mtodo limpar() utilizando a interface:
public void limpar(Object obj) { //Cdigo para limpar uma bola ou um animal... if(obj instanceof EmiteSom) { ((EmiteSom)obj).emitirSom(); }
Perceba que independente do tipo de objeto que vier como parmetro, desde que ele seja do tipo EmiteSom, eu sei que ir possuir a implementao do mtodo emitirSom() e que portanto o cdigo ser executado sem problemas, isto tambm nos permite acabar com aquelas cadeias indesejveis de if's deixando o cdigo mais legvel.
www.t2ti.com
11
public class modulo10Main { public static void main(String[] args) { new RecebeArray(args); System.out.println("Trmino do programa!"); }
public class RecebeArray { public RecebeArray(String[] array) { imprimirPosicao0(array); } public void imprimirPosicao0(String[] array) { System.out.println(array[0]); }
!
}
As setas indicam o fluxo de execuo at o ponto onde ir acontecer a exceo (estrela) o que ocasiona a quebra no fluxo normal da aplicao. Esta execuo pode ser entendida da seguinte forma: Ao invocar o mtodo main, sem o envio de parmetros, instanciado um novo objeto RecebeArray e passado como parmetro do construtor o array vazio, o construtor por sua vez invoca um mtodo desta mesma classe (imprimirPosicao0()) repassando o parmetro recebido, este mtodo tenta imprimir o elemento da posio 0, primeira posio, e o resultado obtido uma exceo, j que o array est vazio. Quando esta exceo acontece o programa encerrado de forma inesperada, perceba que a ltima linha a ser executada (linha grifada em amarelo) no percorrida devido ao trmino inesperado. Podemos observar a visualizao da execuo desta aplicao na figura a seguir:
www.t2ti.com
12
A exceo foi do tipo java.Lang.ArrayIndexOutOfBoundsException que significa a tentativa de acesso a uma posio fora dos limites do array, a seguir ele informa que posio foi, neste caso o ndice 0 (zero). Embaixo da definio da exceo ns temos a stacktrace que contm a seqncia da pilha de execuo. Pela stacktrace possvel perceber quais caminhos a execuo percorreu at alcanar a exceo. A primeira linha da stacktrace contm a definio da exceo, a segunda linha contm o ltimo trecho de cdigo executado com o nmero da linha no cdigo fonte, neste caso foi a invocao do mtodo imprimirPosicao0() da classe RecebeArray, que no cdigo fonte (arquivo RecebeArray.java) refere-se a linha 10. A fim de construirmos programas mais robustos, poderamos tratar situaes como esta. Para isto iremos utilizar o bloco try/catch:
try{ //Cdigo perigoso }catch(Exception e) { //tratamento da exceo }
O bloco try/catch define dois trechos de cdigo, um sujeito a erros (try) e outro que responsvel pelo tratamento do erro caso acontea (catch). Vamos modificar agora a nossa classe RecebeArray e adicionar este bloco ao mtodo imprimirPosicao0():
public class RecebeArray { public RecebeArray(String[] array) { imprimirPosicao0(array); } public void imprimirPosicao0(String[] array) { try{ System.out.println(array[0]); }catch(ArrayIndexOutOfBoundsException e) { System.out.println("Erro: Array vazio, execute o programa novamente" + " passando ao menos um parmetro."); }
www.t2ti.com
13
E agora ao executarmos novamente este mesmo programa o usurio ir receber uma mensagem mais significativa, observe a execuo abaixo:
Pronto! Agora ao executar o programa sem parmetros o usurio saber o que fazer. Porm o mais interessante o seguinte, uma vez que a exceo foi tratada, o programa continua o fluxo de execuo e termina normalmente. Devemos observar o seguinte, esta no a nica exceo que pode acontecer neste mtodo, vamos modificar o mtodo main() de forma que ele encaminhe como parmetro um valor nulo (null).
public class modulo10Main { public static void main(String[] args) { new RecebeArray(null); System.out.println("Termino do programa!"); } }
Repare que agora a nova instncia da classe RecebeArray est recebendo como parmetro uma referncia nula, isto ocasionar uma exceo do tipo java.lang.NullPointerException. Vejamos o resultado da execuo deste cdigo:
www.t2ti.com
14
Perceba agora que, no cdigo destacado, adicionamos mais um bloco de catch que captura todos os tipos de excees veremos mais a frente como est estruturada a hierarquia de classes de excees desta forma caso seja uma exceo do tipo java.lang.ArrayIndexOutOfBoundsException ser tratado no primeiro bloco, todos os demais tipos sero tratados no segundo bloco. O cdigo destacado ir imprimir a mensagem (getMessage()) e na seqncia ir imprimir a stacktrace, importante perceber novamente que aps o tratamento da exceo pelo segundo bloco o programa encerrado normalmente. A seguir temos a execuo do novo programa:
www.t2ti.com
15
Observe que, conforme dito em mdulos anteriores, todas as classes em Java estendem de alguma forma direta ou indiretamente da classe Object. Nesta imagem esto representadas as trs modalidades de excees existentes na linguagem Java: Unchecked Exception, Checked Exception e Error. Error: Hierarquia em laranja na imagem, representam situaes
incomuns, que no so causadas pelo programa, indicam situaes que no acontecem usualmente durante a execuo de um programa (Ex: Estouro da pilha de execuo StackOverflowError); Checked Exception: Hierarquia em cinza, representam situaes que, geralmente, no so erros de programao e sim indisponibilidade de recursos ou condio necessria para a correta execuo inexistente (Ex: Em aplicaes distribudas existe dependncia externa de rede de
www.t2ti.com
16
Exceo
ArrayIndexOutOfBounds Exception ClassCastException IllegalArgumentException IllegalStateException NullPointerException NumberFormatException StackOverflowError NoClassDefFoundError
Quando acontece
Tentativa de acesso a posio inexistente no array. Tentativa de efetuar um cast em uma referncia que no classe ou subclasse do tipo desejado. Argumento formatado de forma diferente do esperado pelo mtodo. O estado do ambiente no permite a execuo da operao desejada. Acesso a objeto que referenciado por uma varivel cujo valor null. Tentativa de converter uma String invlida em nmero. Normalmente acontece quando existe uma chamada recursiva muito profunda. Indica que a JVM no conseguiu localizar uma classe necessria a execuo.
www.t2ti.com
17
A seta indica o uso da palavra reservada throw que responsvel por jogar a exceo, logo a seguir ns instanciamos um objeto do tipo IllegalArgumentException e passamos como parmetro do mtodo construtor o texto que dever aparecer quando a stacktrace for impressa. Veja o resultado da execuo deste mtodo passando o valor -1 (um negativo):
Exception in thread "main" java.lang.IllegalArgumentException: Valor indevido era esperado um valor maior que 0: -1.0 at Veiculo.abastecer(Veiculo.java:10) at modulo10Main.main(modulo10Main.java:6)
www.t2ti.com
18
public void abastecer(Double litros) { if(litros < 0) { throw new QuantidadeLitrosException("Valor indevido. Era esperado um valor maior que 0: "+litros); }else { tanque += litros; } }
Na prtica, so poucos os motivos que nos levam a criar as nossas prprias excees, normalmente as excees existentes nas bibliotecas Java so suficientes para a maioria das ocorrncias.
Exerccios
Aprenda com quem tambm est aprendendo, veja e compartilhe as suas respostas no nosso Frum: Exerccios Mdulo 08 Classes Abstratas, Interfaces e Excees 1. Crie uma classe abstrata que represente um quadriltero e receba como parmetros do construtor os quatro valores referentes a cada lado. 2. Estenda a classe criada no exerccio 1, a subclasse deve representar um quadrado e portanto receber como parmetro um nico valor referente aos seus lados. 3. Estenda novamente a classe criada no exerccio 1, a subclasse deve representar um retngulo e portanto deve receber como parmetros dois valores diferentes. 4. Crie uma interface denominada FiguraGeometrica, adicione os mtodos calcular rea e calcular permetro.
www.t2ti.com
19
www.t2ti.com
20
www.t2ti.com
21