oswaldo poo

241
Programação Orientada a Objetos Prof. Oswaldo Borges Peres O material aqui exposto é fruto do trabalho não só meu, mas principalmente, de muitos professores da Escola de Informática. Com pequenas exceções, eu praticamente juntei e formatei esta apresentação. Agradeço a ajuda de todos os professores que forneceram este material. Sem suas contribuições não seria possível montar este material a tempo.

Upload: abaddon3

Post on 13-Dec-2014

320 views

Category:

Documents


6 download

TRANSCRIPT

Page 1: Oswaldo Poo

Programação Orientada a Objetos

Prof. Oswaldo Borges Peres

O material aqui exposto é fruto do trabalho não só meu, mas principalmente, de muitos professores da Escola de Informática. Com pequenas exceções, eu praticamente juntei e formatei esta apresentação. Agradeço a ajuda de todos os professores que forneceram este material. Sem suas contribuições não seria possível montar este material a tempo.

Page 2: Oswaldo Poo

Aula 01 – Objetivos:

l Conceitos introdutórios de Programação Orientada a Objetos (POO)

l Criação de Classesl Instanciação de objetos

Page 3: Oswaldo Poo

O que é uma Classe?

Uma classe é um tipo de modelo que define como são os objetos que pertencem a esta classe. É como se fosse um projeto que os objetos devem seguir para serem considerados como pertencentes à classe. Neste projeto estão definidos as características (que chamamos de atributos) e os comportamentos que representam as operações que os objetos dessa classe podem realizar (chamamos a isso de métodos).

Page 4: Oswaldo Poo

Exemplos de Classes:

Os animais podem ser classificados em classes, tais como mamíferos, aves, peixes, etc. Cada uma dessas classes tem suas características e comportamentos comuns, que poderiam ser relacionados (descritos) como atributos e métodos dessas classes.

Page 5: Oswaldo Poo

Exemplos de atributos:

Uma classe pessoa, por exemplo, pode ter atributos como nome, endereço, identidade, ou seja, características (dados) específicas de cada pessoa.

Page 6: Oswaldo Poo

Exemplos de métodos:

Uma classe peixe pode ter um método nadar, uma classe pessoa pode ter um método andar ou um método falar, pois estes são comportamentos (ações) típicos destas classes.

Page 7: Oswaldo Poo

O que é um objeto?

Como vimos, uma classe é uma representação de uma entidade do mundo real. Um objeto é uma ocorrência (chamamos a isso de uma instância) de uma determinada classe.

Page 8: Oswaldo Poo

Exemplos de objetos:

l Matheus é um objeto da classe pessoa. Thor(o peixinho do Matheus) é um objeto da classe peixe.

Page 9: Oswaldo Poo

Outros exemplos de objetos:

DemissãoCadastroVendas

Formulário

JoãoMariaCarlos

Empregado

GolPalioCorsa

Carro

ObjetosClasses

Page 10: Oswaldo Poo

Interface, mensagens e encapsulamento

Vamos explorar mais um dos exemplos acima. Como vimos, podemos ter carro como sendo uma classe. As características ou atributos poderiam ser a cor, o modelo, a potência do motor e assim sucessivamente. Os comportamentos ou funcionalidades, poderiam ser ligar e desligar, abrir e fechar a porta, acelerar e frear, e outras ações (operações) que fossem consideradas úteis para descrever um carro.

Page 11: Oswaldo Poo

Interface

Os atributos e métodos da classe carroconstituem o que chamamos de interfacedessa classe com o mundo externo. Um objeto da classe carro só será acessível por outro objeto através de seus métodos, de forma que a interface da classe carro deve definir todosos comportamentos desejáveis a um objeto desta classe.

Page 12: Oswaldo Poo

Encapsulamento

O fato dos objetos esconderem sua forma de funcionamento é um conceito importante em OO, e está ligado à existência da interface. Somente a classecarro conhece a forma de funcionamento(implementação) de seus métodos. É o que chamamos de encapsulamento. Ou seja, conhecemos as características e as funcionalidadesde um carro, mas não sabemos (nem precisamos saber) quais técnicas e processos os projetistas utilizaram para a construção do projeto, ou seja para implementar a forma de funcionamento de seus métodos.

Page 13: Oswaldo Poo

Mensagens

Uma vez que tenhamos definido a interface da classe carro e que tenhamos um objeto dessa classe, como fazer para que ele execute a operação ligar? Devemos enviar uma mensagem para esse carro (ligue!) e ele executará a operação. Nós (externamente ao objeto) é que pedimos ao objeto para que execute essa operação, sem precisar saber como o carro faz para ligar (que tipo de algoritmo ele usa para isso). O mesmo ocorre se quisermos saber a cor do carro. Simplesmente perguntamos (qual é a sua cor?) e o carro responde (naturalmente precisaríamos ter criado um método que respondesse a isso). Onde e como ele armazena a informação da cor não é relevante. Apenas sabemos que ele é capaz de armazenar seus atributos e informá-los quando necessitarmos deles.

Page 14: Oswaldo Poo

Representação do problema - UML

Para estudarmos a Programação Orientada a Objetos (POO), é necessário que entendamos a Modelagem Orientada a Objetos (MOO). Essa técnica representa as estruturas através de uma linguagem padrão, conhecida como UML (Unified Modeling Language), usada para a criação de modelos que representam os problemas do mundo real. A UML classifica os “objetos” envolvidos no domínio do problema e define as formas como os mesmos se relacionam. Não é o nosso foco uma abordagem profunda dos conceitos e ferramentas da UML. Utilizaremos apenas os principais elementos da MOO, que são necessários para dar andamento à POO. Para implementação utilizaremos a linguagem Java.

Page 15: Oswaldo Poo

Representação do problema - UML

l Na UML as classes são representadas na forma de caixas com, no máximo, três compartimentos. O primeiro deles contém o nome da classe (sempre no singular e com a primeira letra em maiúsculo), o segundo contém a lista de atributos e o terceiro contém a lista de operações. Veja a classe carro:

l A UML (e o Java) sugere que todos os nomes de atributos e métodos se iniciem com letra minúscula. Na classe Carro foram criados três atributos: dois do tipo String, marca e cor e o terceiro, motorEstado, é um booleano que indica se o motor está desligado ou ligado.

Page 16: Oswaldo Poo

Representação do problema - UML

Além dos atributos da classe, queremos também criar métodos que contenham as operações que objeto poderárealizar. Um carro pode fazer muitas coisas, mas, para manter a simplicidade, vamos criar inicialmente apenas três métodos:

– O primeiro é o método ligaMotor, que muda o estado do motor para ligado, isto é, para true e depois exibe uma mensagem de aviso.

– O segundo é o método desligaMotor, que muda o estado do motor para desligado, isto é, para false e depois exibe uma mensagem de aviso.

– O terceiro método, mostraAtributos, exibe os valores dos atributos de um objeto ou instância da classe Carro.

Page 17: Oswaldo Poo

Exemplo:

l Edite o texto abaixo que contém os atributos e métodos da classe Carro:

public class Carro {String marca; String cor; boolean motorEstado;void ligaMotor() {motorEstado = true;System.out.println("O motor foi ligado.");

}void desligaMotor() {motorEstado = false;System.out.println("O motor foi desligado.");

}void mostraAtributos() {System.out.println("O carro tem a cor " +

cor + "e eh da marca " + marca);if (motorEstado == true)

System.out.println("O motor jah estah ligado.");else {

System.out.println("O motor estah desligado.");}

}}

Page 18: Oswaldo Poo

Exemplo(Continuação)

l Crie também um objeto dessa classe. Em Java podemos fazer isso adicionando o método main à classe Carroe nele instanciando efetivamente um objeto da classe Carro (comando new).

public static void main (String args[]) {Carro meuCarro = new Carro(); // instancia o objetomeuCarro.marca = "Palio"; // inicia o atributo marcameuCarro.cor = "azul"; // inicia o atributo corSystem.out.println("Mostrando os atributos:");meuCarro.mostraAtributos(); //mensagem para o objeto

System.out.println("---------");System.out.println("Ligando o motor...");meuCarro.ligaMotor(); //mensagem para ligar o carroSystem.out.println("Mostrando os atributos:");meuCarro.mostraAtributos();

System.out.println("---------");System.out.println("Desligando o motor...");meuCarro.desligaMotor();System.out.println("Mostrando os atributos:");meuCarro.mostraAtributos();

}

Page 19: Oswaldo Poo

Exemplo (Continuação)

l Salve o texto acima como Carro.java. A seguir, para compilar o código criado, usaremos o compilador javac: abra uma tela de comandos do Windows, vá para o diretório onde foi salvo o arquivo Carro.java e digite: javac Carro.java

l O programa deve compilar normalmente (se não reconhecer o comando é necessário alterar o path da máquina para incluir o diretório onde se encontra o compilador javac). Será gerado um arquivo Carro.class. A seguir, vamos executar o arquivo com o comando: java Carro

Page 20: Oswaldo Poo

Desafios

l 1. Crie o objeto outroCarro da classe carro com a marca Gol e a cor prata.

l 2. Insira um novo atributo rotacaoMotor e inicie-o com zero. O método ligaMotor deve atualizar esse atributo para 1000 e o método desligaMotor deve atualizá-lo para zero.

l 3. Crie um novo método acelerar que some 100 ao valor corrente do atributo rotacaoMotor. Crie também o desacelerar, que subtraia 100.

l 4. A partir do arquivo criado, desmembre-o em dois. O arquivo jáexistente, de nome Carro, só com a classe Carro sem o método main. E outro arquivo, denominado principal, só com o método main.5 . Crie uma classe Quadrado que tenha um atributo lado e métodos para informar a área e o perímetro. Varie a arquitetura da aplicação.

Page 21: Oswaldo Poo

Dicas sobre a instalação do Java

l O SDK, Software Development Kit– O SDK não é um ambiente visual de programação. É composto

apenas de ferramentas que devem ser utilizadas através da linha de comando (no Windows, em uma janela DOS). Atualmente é chamado de J2SE, Java 2 Standard Edition. Deve ser usado um editor de texto qualquer como o Notepad, mas existem alguns editores que incorporam funções de compilação e execução como o Textpad, o JCreator ou o BlueJ (todos necessitam do SDK para estas funções).

– Existem ambientes de desenvolvimento integrados como o NetBeans, o Eclipse, o JBuilder da Borland ou o Visual Café da Symantec, mas vamos preferir o caminho mais indicado para aprendizagem de JAVA, que é utilizar apenas um editor de texto e o SDK.

Page 22: Oswaldo Poo

Dicas sobre a instalação do Java

l Instalação do SDK (versão 1_5_0_07):– Executar o arquivo jdk-1_5_0_07-windows-i586-p.exe (ou a versão mais atual

que estiver disponível em java.sun.com). Serão instalados, no diretório que você escolher, o JAVA 2 SDK (diretório ..\jdk1.5.0_07), que contém o compilador e o interpretador JAVA, e o JRE (JAVA Runtime Environment), no subdiretório ..\jre1.5.0_07, que contém o JVM (JAVA Virtual Machine) e o plugin JAVA para os seus navegadores.

– Descompactar o arquivo \ jdk1.5.0_07\src.zip no próprio diretório.– As ferramentas do SDK deverão ser acessadas a partir de qualquer diretório

de trabalho, por isso teremos que adicionar o diretório bin do SDK ao PATH. No Windows acione o menu propriedades do MeuComputador e, na aba Avançados, escolha o botão Variáveis de Ambiente e edite o PATH de variáveis do sistema para incluir o diretório ..\jdk1.5.0_07\bin. Reiniciar o computador.

Page 23: Oswaldo Poo

Dicas sobre a instalação do Java

l Sobre os Nomes de Arquivos JAVA– Os nomes de arquivos em JAVA são nomes de arquivos

extensos, maiores que o padrão DOS 8.3 (nome com oito caracteres e extensão com três), pois a extensão deve ser “.java" e o nome do arquivo deve ser o mesmo nome da classe, em geral com mais de oito caracteres.

– JAVA é Case Sensitive, ou seja, diferencia maiúsculas e minúsculas. Devemos então tomar cuidado ao escrever um nome de arquivo ou de classe JAVA.

Page 24: Oswaldo Poo

Dicas sobre a instalação do Java

l Exemplo 2.1: Welcome.java (modificado de: Core Java 2, vol.1, página 29)

public class Welcome{ public static void main (String[] args){

String[] greeting = new String[2];greeting[0]="Welcome to Core JAVA";greeting[1]="by Cay Horstmann and Gary Cornell";int i;

for (i = 0; i < greeting.length; i++)System.out.println(greeting[i]);

}}

Page 25: Oswaldo Poo

Dicas sobre a instalação do Java

– Salvar o arquivo com o nome “Welcome.java” (o programa tem que ter o mesmo nome da classe, escrito da mesma maneira e com extensão “.java”). Usar a opção “Salvar com o tipo: Todos os arquivos (*.*)”, salvando em um diretório criado para os exemplos JAVA.

– Abrir uma janela de comando e executar os seguintes:l cd seudiretorio [ENTER]l javac Welcome.java [ENTER]l java Welcome [ENTER]

– O programa javac é o compilador JAVA. Ele compila o arquivo “Welcome.java” gerando o arquivo “Welcome.class”.

– O programa java é o interpretador JAVA. Ele interpreta os bytecodes que o compilador colocou no arquivo classe.

– Pronto. Se tudo funcionou, seu compilador está bem instalado e estamos prontos pra continuar nossos estudos.

Page 26: Oswaldo Poo

Aula 02 – Objetivos:

l Reforçar o conceito de encapsulamentol Apresentar métodos parametrizadosl Introduzir os níveis de acessibilidade de

atributos e métodosl Esclarecer o uso dos construtores

Page 27: Oswaldo Poo

Recordando...

Na aula passada criamos uma classe Carro, na qual havia alguns atributos e métod os. Na classe que usamos para instanciar e testar um objeto da classe Carro, que chamamos de classe Principal, iniciamos diretamente os atributos do objeto meuCarro, logo após instanciá-lo. Entretanto, esta NÃO é a forma mais adequada de fazer isso.

De fato, ao projetarmos uma classe, devemos ter em mente que o conceito de encapsulamento é muito importante na POO. Isto significa que os métodos da classe devem, geralmente, ser os únicos responsáveis pelo acesso aos atributos da classe. Isso “esconde” o modo de funcionamento da classe, privilegiando o uso da interface da classe como forma única de acesso, o que facilita o teste, a manutenção e a reusabilidade das mesmas.

Page 28: Oswaldo Poo

Uma forma mais adequada

Para evitarmos iniciar os atributos da classe fora da mesma, devemos criar métodos na própria classe que façam esse acesso, tanto de escrita quando de leitura, sempre que necessário.

Podemos alterar a classe Carro, introduzindo um método configurarCarro, que seja responsável pela iniciação dos atributos. Entretanto, como passar os valores que desejamos para os atributos do carro? A resposta é: através de argumentos no método. Ao enviarmos uma mensagem para um objeto da classe Carro através do método configurarCarro, devemos especificar os valores desejados para o carro (que chamamos de parâmetroscorrespondentes aos argumentos). Ou seja, o método configurarCarro deve estar apto a receber esses parâmetros como argumentos e atribuí-los aos atributos do carro (por vezes os termos parâmetros e argumentos são usados indiferentemente, mas argumentos são tipos formais e parâmetros são valores reais).

Page 29: Oswaldo Poo

Uma forma mais adequada(Cont...)

O código a seguir prepara o método configurarCarro para receber os argumentos desejados para a classe Carro:

void configurarCarro(String m, String c, boolean e) {marca = m;cor = c;motorEstado = e;

}Na classe Principal, para realizar a chamada do método, agora

devemos passar os parâmetros adequados aos argumentos, da seguinte forma:

meuCarro.configurarCarro("Palio","azul",false);Edite, compile e teste o funcionamento da alteração do código.

Page 30: Oswaldo Poo

Uma forma mais adequada(Cont...)

Na parte de Desafios da aula 1 foram criados o atributo rotacaoMotor e os métodos acelerar e desacelerar. Estes métodos também podem ser reescritos para receber como parâmetros os valores a serem somados ou subtraídos do atributo rotacaoMotor. A inclusão do atributo fica assim:

int rotacaoMotor;O código dos métodos acelerar e desacelerar fica assim:

void acelerar(int parcela) {rotacaoMotor += 100;System.out.println(“Motor foi acelerado para "+ rotacaoMotor+“RPM.");

}void desacelerar(int parcela) {

rotacaoMotor -= 100;System.out.println(“Motor foi desacelerado para "+rotacaoMotor+"RPM.");

}E as chamadas dos métodos na classe principal ficam assim:

System.out.println("---------"); System.out.println("Acelerando o motor...");meuCarro.acelerar(100);System.out.println("---------"); System.out.println("Desacelerando o motor...");meuCarro.desacelerar(100);

Edite, compile e teste o funcionamento da alteração do código.

Page 31: Oswaldo Poo

Definindo a acessibilidade(Visibilidade)

De fato, a correção feita no código da classe Carro foi positiva, mas não impede o uso indevido dos atributos por uma classe externa. Para tanto, devemos utilizar o recurso de definir a acessibilidade do elemento (classe, atributo ou método). Fazemos isso, em Java, usando as palavras reservadas public, private, package e protected na declaração.

Os atributos e métodos public constituem a interface da classee são acessíveis a qualquer método de qualquer classe externa. Os atributos e métodos private são de acesso exclusivo dos métodos da classe. Os de acessibilidade protected são passíveis de acesso por métodos de classes que herdem da classe que os definiu (trabalharemos esse conceito mais adiante). O nível package, que éassumido como padrão quando nenhum nível de acessibilidade éexplicitamente definido (o que é o caso do nosso exemplo da aula passada), define o atributo ou método como acessível para qualquer método de classe dentro do mesmo pacote (este conceito também será trabalhado mais adiante).

Page 32: Oswaldo Poo

Definindo a acessibilidade(Visibilidade)

No nosso caso, desejamos restringir o acesso aos atributos da classe Carro. Para tanto, vamos defini-los como private. Altere assim o código:private String marca;private String cor;private boolean motorEstado;private int rotacaoMotor;

Agora tente acessar os atributos como feito na aula passada...Pois é, a linguagem impede o acesso dessa forma, pois ela passou a ser errada.

Page 33: Oswaldo Poo

Mais sobre parametrização – set e get

Além de passarmos parâmetros para os métodos de uma classe durante uma mensagem, podemos também receber dados dos métodos chamados. Uma forma de fazê-lo é definir um valor de retorno para um método chamado. Os campos private de uma classe só podem ser manipulados por métodos dessa classe. Qualquer objeto de outra classe(um cliente, portanto), que deseje acessar um campo private da classe servidora, deve chamar os métodos public que a esta ofereça para manipular seus campos private. As classes costumam oferecer métodos public para permitir aos clientes da classe configurar (set - atribuir) ou obter (get - obter) valores das variáveis private. Os nomes desses métodos não precisam começar com set ou get, mas essa convenção de atribuição de nomes é altamente recomendada em Java. Por exemplo, podemos criar um método getRotacaoMotor que retorne o valor do atributo rotacaoMotor. Assim:

int getRotacaoMotor () {return rotacaoMotor;

}

Page 34: Oswaldo Poo

Mais sobre parametrização – set e get (Cont...)

Para chamarmos o método, poderíamos usar este código:System.out.println("Rotacao do motor = " +

meuCarro. getRotacaoMotor () + " RPM."); Da mesma forma, caso quiséssemos criar um método setRotacaoMotorque configurasse o valor do atributo rotacaoMotor, ele seria assim:

int setRotacaoMotor (int r) {rotacaoMotor = r;

}e a atribuição de uma valor à rotação teria, portanto, a seguinte sintaxe:

meuCarro.setRotacaoMotor (1000)

Page 35: Oswaldo Poo

Criando objetos com o uso de construtores

A criação do método configurarCarro foi uma boa idéia para melhorar o encapsulamento da classe. Entretanto, ainda não é a melhor forma de iniciar os valores dos atributos. Melhor seria utilizarmos um método especial, que chamamos Construtor. O construtor de uma classe é um método automaticamente chamado quando instanciamos um objeto dessa classe. Em Java, o método construtor tem o mesmo nome da classe e échamado quando usamos o comando new. Reparando bem, no exemplo da classe carro temos: new Carro(); o que sugere que estamos chamando um método chamado Carro (o uso dos parêntesis é um indicativo disso). Entretanto onde está este método que não foi declarado? A resposta é que a linguagem pressupõe que toda classe tem um construtor padrão (default), que não possui argumentos e inicia os atributos numéricos com zero e os atributos lógicos com false. Entretanto, podemos definir explicitamente o construtor da classe, fazendo com que ele seja responsável pela iniciação de atributos da classe com valores distintos dos valores padrão. Assim, podemos ter:

public Carro () {marca = "Palio";cor = "azul";motorEstado = true; rotacaoMotor = 1000;

}

Page 36: Oswaldo Poo

Criando objetos com o uso de construtores(Cont...)

Bem, o construtor é um método como os demais e, portanto, também pode receber argumentos. Assim, poderíamos melhorar o nosso construtor permitindo que recebesse como parâmetros os valores a serem postos inicialmente em alguns atributos. Um código possível seria:

public Carro (String m, String c) {marca = m;cor = c;motorEstado = true; rotacaoMotor = 1000;

}Uma classe pode possuir mais de um construtor. Eles devem ter o

mesmo nome e diferenciar-se apenas pelo número de argumentos que recebem. Isto é chamado de sobrecarga de construtor (veremos o assunto sobrecarga de métodos, em detalhes, mais à frente). Desta forma, podemos ter diferentes construtores, permitindo flexibilizar a criação e a iniciação dos atributos dos objetos em diferentes situações que se façam necessárias.

Page 37: Oswaldo Poo

Desafios

l Crie métodos set e get para todos os atributos private da classe Carro.l Crie um novo construtor que receba também o estado em que o motor

deve ser iniciado e inicie a rotação de acordo com o estado passado como argumento: 0 (para motor desligado) ou 1000 (para motor ligado).

l Para a classe Quadrado, criada no desafio da aula passada, crie também métodos get e set para o atributo lado.

l Crie uma classe Livro, que possua atributos para nome, autor, edição, editora e ano de publicação. Os atributos devem ser privados e devem possuir métodos de acesso. Deve haver um método que imprime os atributos correntes do livro. Deve haver um construtor padrão que inicia os atributos com o valor ‘desconhecido’ e a seguir imprime uma mensagem de saudação com os atributos correntes. Deve haver construtores alternativos para instanciar os objetos da classe Livro com os respectivos parâmetros correspondentes aos atributos. Adicionalmente, crie um programa principal que instancie diferentes livros chamando os diferentes construtores e os métodos get e set dos atributos que se fizerem necessários.

Page 38: Oswaldo Poo

Aula 03: Objetivos

l Introduzir o conceito de herançal Criar uma hierarquia de classes l Detalhar o funcionamento da herança l Rever o uso dos modificadores de acesso

Page 39: Oswaldo Poo

Recordando...

Nas aulas passadas criamos uma classe Carro, que apresentava alguns atributos (cor, marca, motorEstado) e alguns métodos (acelerar, desacelerar, etc). Se quiséssemos criar uma outra classe Caminhao, certamente várias características, tanto atributos como comportamentos (métodos), seriam parecidos ou mesmo iguais aos da classe Carro. Caso semelhante ocorreria se quiséssemos criar um carro elétrico. Nestas situações, ao invés de criarmos uma série de classes, desvinculadasumas das outras, mas com várias coisas em comum, a MOO utiliza um conceito que permite criar uma relação entre as classes.

Page 40: Oswaldo Poo

Herança

O conceito de herança permite estabelecer uma hierarquia entre as classes. É um mecanismo que permite a uma classe herdar as operações e os atributos de outra classe. Com o uso da herança, quando se escreve uma classe é necessário especificar apenas no que ela édiferente da classe-mãe, classe-base ou superclasse. O mecanismo da herança dá acesso automático às informações contidas na classe base. Através da herança, uma classe possui imediatamente toda a funcionalidade de uma classe já existente. A classe que herda características da outra é chamada subclasse ou classe-filha e a classe que fornece a herança é chamada superclasse ou classe-mãe.

A herança é, portanto, o compartilhamento de atributos e operações entre classes, baseado em um relacionamento hierárquico do tipo pai-filho (ou mãe-filho), em que a classe pai possui definições que podem ser utilizadas nas classes filhas. Estas funcionam como uma especialização da classe pai (as filhas estendem a sua utilização básica da classe pai para outras utilizações mais especializadas).

Page 41: Oswaldo Poo

Herança

A seguir uma figura ilustrativa do conceito de herança:

Page 42: Oswaldo Poo

Herança

Uma superclasse direta é a superclasse a partir da qual a subclasse herda explicitamente. Uma superclasse indireta équalquer superclasse acima da superclasse direta. Desta forma, no exemplo acima, Mamifero e uma superclasse direta de SerHumano e Animal é uma superclasse indireta de SerHumano.

Page 43: Oswaldo Poo

Herança em Java

Todas as classes, tanto as que são escritas pelo programador quanto aquelas da biblioteca de classes do Java, são organizadas em uma hierarquia. No topo da hierarquia de classes está a classe Object. Todas as classes são herdeiras desta superclasse. Object éa classe mais geral da hierarquia, ela define o comportamento herdado por todas as classes da hierarquia de classes do Java.

Em Java, uma classe pode ter apenas uma superclasse (Java não suporta herança múltipla, como a existente em C++, por exemplo), mas cada classe pode ter um número ilimitado de subclasses. Se a superclasse tiver comportamentos e atributos que sua classe precisa, você não precisa redefini-la ou copiar esse código para ter o mesmo comportamento e atributos. Sua classe recebe automaticamente as características de sua superclasse. Essa superclasse também recebe da sua superclasse e assim por diante, formando uma cadeia até o inicio da hierarquia. Sua classe é, portanto, uma combinação de todos os recursos das classes que estão acima dela na hierarquia, assim como de seus própriosrecursos.

Page 44: Oswaldo Poo

Herança em Java

Em Java, indicamos que uma classe herdacaracterísticas de outra através da palavra reservada extends. O código abaixo ilustra isso:

public class Animal { ...

}public class Mamifero extends Animal {

...}

Page 45: Oswaldo Poo

Herança em Java

Voltemos ao exemplo da classe Carro. Poderíamos criar um projeto mais completo, com uma classe mais geral chamada Veículo. A figura ao lado ilustra como poderíamos estruturar o projeto.

Na classe Veículo definiríamos apenas características ou operações comuns a qualquer subclasse, tais como: cor, marca, etc. Abaixo da classe Veículo, as subclasses Carro e Caminhão teriam atributos e operações específicos de cada uma.

Utilizando a herança é possível definir uma característica ou uma operação apenas uma vez na hierarquia. A partir daí ela é reutilizada automaticamente por cada subclasse.

Page 46: Oswaldo Poo

Herança em Java

Quando se cria uma nova instância de uma classe, écriado um espaço para cada atributo definido na classe corrente e nas superclasses.

Os métodos funcionam de modo semelhante: os novos objetos têm acesso a todos os nomes de métodos de sua classe e de suas superclasses. Isso édeterminado dinamicamente, quando um método éutilizado em um programa que está em execução. Ao chamar um método de um objeto em particular, o interpretador Java procurará primeiramente na classe do objeto por esse método. Se o método não for encontrado, o interpretador procurará na superclasse dessa classe e assim por diante, até que a definição do método seja encontrada

Page 47: Oswaldo Poo

Herança em Java

Suponhamos, por exemplo, que tenha sido declarada a seguinte classe:

class poligono{int cx, cy; // coordenadas do centro do polígono

}

Agora suponhamos que pretendamos criar uma classe que tenha as dimensões do quadrado, além das coordenadas do centro. Basta fazer:

class Quadrado extends Polígono {int lado; // Comprimento do lado do quadrado

}

Page 48: Oswaldo Poo

Herança em Java

A classe Quadrado é uma classe derivada da classe Polígono, da qual herda todos os dados e os métodos nela contidos.

Um problema com herança é que uma subclasse pode herdar métodos que ela não necessita ou que não deveria ter. Mesmo quando um método é adequado a uma subclasse, essa subclasse precisa freqüentemente de uma versão personalizada de método. Nesses casos, a subclasse pode sobrescrever (redefinir) o método da superclasse com uma implementação mais adequada.

Observações sobre acessibilidade na estrutura de herança:l Todos os membros de superclasse public e protected mantêm

seu modificador de acesso quando se tornam membros da subclasse.

l Os métodos de subclasse podem referir-se a membros public e protected herdados da superclasse simplesmente utilizando os nomes dos membros. Quando um método de subclasse sobrescrever um método de superclasse, o método da superclasse pode ser acessado a partir da subclasseprecedendo o nome do método da superclasse com a palavra-chave super e o separador (.)

Page 49: Oswaldo Poo

Herança em Java

Para observarmos um relacionamento entre superclasse e subclasse, utilizaremos uma hierarquia de herança que contém tipos de empregados em um aplicativo de folha de pagamento. Na empresa, os empregados comissionados recebem apenas uma porcentagem (comissão) de suas vendas, enquanto que os empregados fixos comissionados recebem um salário base mais a comissão.

Page 50: Oswaldo Poo

Herança em Java

Vamos inicialmente criar a superclasse EmpComissionado em um arquivo de mesmo nome da classe, portanto, EmpComissionado.java.

//Classe Empregado Comissionadopublic class EmpComissionado extends Object {

protected String nome;protected String sobrenome;protected String cpf;protected double totalVendas;protected double taxaComissao;

// Construtor com 5 argumentospublic EmpComissionado (String n, String sn,

String cic, double vendas,double comissao){nome = n;sobrenome = sn;cpf = cic;setTotalVendas (vendas);setTaxaComissao (comissao);

}

Page 51: Oswaldo Poo

Herança em Java

public void setNome (String n){nome = n;}public String getNome() { return nome;

}public void setSobrenome (String sn){sobrenome = sn;

}public String getSobrenome() {

return sobrenome;}public void setCpf (String cic){

cpf = cic;}public String getCpf() {

return cpf;}

Page 52: Oswaldo Poo

Herança em Java

public void setTotalVendas (double vendas){totalVendas = (vendas < 0.0) ? 0.0 : vendas;

}

public double getTotalVendas () {return totalVendas;

}

public void setTaxaComissao (double tx){taxaComissao = (tx < 0.0) ? 0.0 : tx;

}

public double getTaxaComissao () {return taxaComissao;

}

public double salario(){ // Calcula o salárioreturn taxaComissao * totalVendas;

}

Page 53: Oswaldo Poo

Herança em Java

public String toString () { return String.format (

"%s%s %s\n%s%s\n%s%.2f\n%s%.2f\n%s%.2f","Identificacao do empregado: ",

nome, sobrenome,"CPF: ", cpf,"Total de Vendas: ", totalVendas,"Taxa de Comissão: ", taxaComissao,"Salario Total: ", salario() );

}

} // fim da classe Empregado Comissionado

Page 54: Oswaldo Poo

Herança em Java

A seguir vamos, criar a subclasse EmpFixoComissionado, que herda todos os atributos e métodos da superclasse EmpComissionado. Observe que a subclasse chama alguns métodos da superclasse, a começar pelo próprio construtor desta (lembre-se de colocar o código abaixo em um outro arquivo com o mesmo nome da classe).

//Classe Empregado com salário base mais Comissãopublic class EmpFixoComissionado extends EmpComissionado {

private double salarioBase; // atributo exclusivo

public EmpFixoComissionado ( //constructor da classeString n, String sn, String cic, double vendas,double comissao, double salBase){

// chama construtor da superclassesuper (n, sn, cic, vendas, comissao);

// chamada a método da própria classesetSalarioBase (salBase);

}

Page 55: Oswaldo Poo

Herança em Java

public void setSalarioBase (double salBase){salarioBase = (salBase < 0.0) ? 0.0 : salBase;

}

public double getSalarioBase() {return salarioBase;

}

public double salario(){ // Calcula o salárioreturn salarioBase + super.salario();

}

// Retorna as informaçõespublic String toString () { return String.format ("%s \nSalario Base: %.2f",

super.toString(), salarioBase); }

} // fim da classe Empregado Fixo Comissionado

Page 56: Oswaldo Poo

Herança em Java

Finalmente, vamos fazer uma aplicação que use as classes criadas (edite essa aplicação de teste em um terceiro arquivo, que deve se chamar Principal.java):

// Testando a classe Empregado fixo com comissãopublic class Principal{ // Método mainpublic static void main ( String argv[]) { // Instancia objeto da classe

EmpFixoComissionadoEmpFixoComissionado empregado =

new EmpFixoComissionado ("Roberto", "Silveira", "123456789-10", 20000, 0.02, 300);// obtém os dados do empregadoSystem.out.println ("Dados do empregado: \n");System.out.printf ("%s %s\n", "Nome: ", empregado.getNome() );System.out.printf ("%s %s\n", "Sobrenome: ", empregado.getSobrenome() );System.out.printf ("%s %s\n", "CPF: ", empregado.getCpf() );System.out.printf ("%s %.2f\n", "Vendas: ", empregado.getVendas() );System.out.printf ("%s %.2f\n", "Comissao: ", empregado.getTaxaComissao() );System.out.printf ("%s %.2f\n", "Salario total: ", empregado.salario() );System.out.printf ("%s %.2f\n", "Salario base: ", empregado.getSalarioBase() );

System.out.printf ("\n%s: \n\n%s\n", "As mesmas informacoes do empregado via toString", empregado.toString() );

} // fim do método main} // fim da classe Principal

Page 57: Oswaldo Poo

Desafios

1. Altere o moderador de acesso do método salario() da classe EmpComissionado de public para private e compile este arquivo. A seguir compile o arquivo com a classe EmpFixoComissionado. Explique o erro de compilação.

2. Na classe de teste, crie um objeto da classe EmpComissionadoe teste-o

3. Crie um atributo bonus que represente um percentual a ser acrescido ao salário. Este bonus se aplica a todos os empregados mas deve ser contado em dobro para os empregados comissionados. Faça as alterações nos métodos que julgar necessárias para realizar o novo cálculo.

Page 58: Oswaldo Poo

Aula 04: Objetivos

l Compreender tipos estáticos e dinâmicosl Definir o conceito de polimorfismo de métodol Apresentar classes e métodos abstratosl Esclarecer o uso do operador thisl Apresentar classes e métodos final

Page 59: Oswaldo Poo

Recordando...

Na aula passada, empregando o conceito de herança, criamos uma subclasse EmpFixoComissionado que herda atributos e métodos de uma superclasse EmpComissionado. Quando fizemos um método para calcular o salário em cada uma dessas classes, utilizamos a técnica de escrever o método salário() na superclasse e sobrescreve-lo na subclasse. Assim, ao chamarmos salário(), vimos que o método efetivamente chamado era o primeiro encontrado de baixo para cima (da subclasse para a superclasse). Isto ocorreu porque a resolução de qual método chamar é dinâmica (depende do tipo do objeto efetivamente instanciado), independentemente do tipo estático da variável. Isto não ficou claro na aula passado porque os objetos tinham tipos estáticos e tipos dinâmicos iguais. Vejamos a seguir como poderia ser diferente.

Page 60: Oswaldo Poo

Tipagem estática x dinâmica

De fato, de forma diferente do que vimos, poderíamos ter uma variável declarada como sendo de um determinado tipo estático (classe), mas efetivamente sendo instanciada como um objeto de uma subclasse. Por exemplo, poderíamos ter:

EmpComissionado empregado = new EmpFixoComissionado(“Ana","Silva","123456789-10",20000,0.02,300);

Note que, neste caso, o tipo estático da variável empregado é o da superclasse EmpComissionado, mas o objeto efetivamente instanciado éde fato da subclasse EmpFixoComissionado. Após esse comando, se o método salário() for chamado, o método acionado será o da subclasse.

Essa característica é chamada Polimorfismo de Método, mas sóé possível determinar isso dinamicamente (em tempo de execução), após sabermos de qual classe o objeto foi efetivamente instanciado.

Page 61: Oswaldo Poo

Classes e métodos abstratos

Ainda no exemplo da aula passada, o que fizemos foi criar duas classes utilizando o conceito de herança e colocar na superclasse o que era comum às duas classes. Entretanto, cabe observar que era previsto haver empregados (objetos, portanto) de ambas as classes (EmpComissionado e EmpFixoComissionado).

Existem situações em que classes possuem um conjunto de características comuns que, entretanto, não é suficiente para que com ele seja possível definir objetos reais. Esse conjunto de características comuns é então separado em uma superclasse destinada apenas a definir o que é comum às subclasses dela derivadas, sem que se tenha a intenção de efetivamente instanciar objetos dessa classe. Tal classe é conhecida como Classe Abstrata.

Page 62: Oswaldo Poo

Classes e métodos abstratos

Para o projeto da aula anterior poderíamos ter criado a estrutura ao lado, onde Empregado fosse uma classe reservada para conter as características comuns a todos os empregados. Essa classe, entretanto, não possuiria todos os dados necessários para definir um empregado real, o que implica em que não haveránenhum objeto real dessa classe, caracterizando-a como uma classe abstrata.

Page 63: Oswaldo Poo

Classes e métodos abstratos

Essa classe deve conter apenas atributos que sejam comunsa todos os empregados, como nome, sobrenome e CPF. Nas classes derivadas é que aparecerão atributos relacionados àforma de contratação e que influenciam a remuneração dos empregados, tais como total de vendas, bônus, horas trabalhadas, salário base, etc.

Nesse contexto, para que possamos utilizar corretamente o polimorfismo de método no cálculo do salário, devemos definir um método abstrato salário() na superclasse Empregado. Tal método não deve possuir efetivamente nenhuma implementação, pois não é sequer possível calcular o salário nessa classe. O código efetivo de implementação do método salário() deve ser deixado a cargo das subclasses, que possuem as informações necessárias para realizar o cálculo do salário. Esse método da superclasse Empregado é chamado de Método Abstrato e sua sobreposiçãonas subclasses permite o Polimorfismo de Método.

Page 64: Oswaldo Poo

Classes e métodos abstratos

Na aula passada, quando implementamos diferentes versõespara o método construtor de uma classe, fizemos uma Sobrecarga de Método. De fato podemos fazer isto com qualquer método da classe. Como visto no caso do construtor, o que diferencia essas implementações e permite à linguagem determinar qual implementação efetivamente chamar é a quantidade de argumentos definidos em cada uma e a quantidade de parâmetros passados na chamada do referido método.

No exemplo de hoje, que será uma adaptação do exemplo da aula passada, faremos uma sobrecarga do método salario na classe EmpAssalariado, de forma a permitir dois cálculos diferentes para o salário, um com um abono (passado como parâmetro) e outro sem abono.

Page 65: Oswaldo Poo

Operador this

Novamente recordando a aula passada, quando criamos os métodos parametrizados, declaramos os argumentos com nomes “parecidos” com os atributos da classe. Fazendo dessa forma, ficou claro que o argumento é uma variável e o atributo é outra, como, por exemplo, em:public EmpComissionado (String n, String sn,

String cic, double vendas,double comissao){nome = n;sobrenome = sn;cpf = cic;setTotalVendas (vendas);setTaxaComissao (comissao);

}

Page 66: Oswaldo Poo

Operador this

No construtor acima estamos lidando com dez variáveis (cinco argumentos do método e cinco atributos da classe). Esta forma, entretanto, não favorece a compreensão, na medida que alguns nomes de argumentos são bastante esclarecedores do seu conteúdo e criar um sinônimo pode ser indesejável. Porem, razões sintáticas nos fizeram utilizar os sinônimos, pois se o argumento sn, por exemplo, fosse chamado sobrenome, teríamos o comando de atribuição:

sobrenome = sobrenome;

que não seria corretamente compreendido pelo compilador. Neste caso estamos diante de uma sobrecarga de nome e o compilador resolve isso escolhendo a referência mais próxima (a que foi definida por último). Portanto, a variável sobrenome referenciada nesse comando não seria o atributo da classe e sim o argumento do método (o último definido).

Page 67: Oswaldo Poo

Operador this

Soluciona-se isso usando o operador this, que faz referência ao objeto atual (objeto corrente ao tempo da execução). Assim o trecho de programa anterior poderia ser mais elegantemente definido assim:

public EmpComissionado (String nome, String sobrenome, String cpf, double totalVendas,double taxaComissao){this.nome = nome;this.sobrenome = sobrenome;this.cpf = cpf;setTotalVendas (totalVendas);setTaxaComissao (taxaComissao);

}O mesmo se aplica aos demais métodos, como, por exemplo, aos métodos set dos atributos das classes.

Page 68: Oswaldo Poo

Classes e métodos final

Podem ocorrer situações em que não seja desejável permitir que eventuais subclasses sobrescrevam métodos de uma superclasse. Nestes casos devemos impedir a redefinição do método através do uso de uma palavra reservada na declaração do mesmo. As declarações de métodos precedidas pela palavra reservada final não podem ser sobrescritas em subclasses. Os métodos declarados como private são implicitamente final porque é impossível sobrescrevê-los em uma subclasse. Como as implementações dos métodos final não podem mudar, todas as subclasses utilizam a mesma implementação do método, e as chamadas a métodos final são resolvidas em tempo de compilação, o que é conhecido como vinculação estática.

Uma classe declarada como final não pode ser superclasse, ou seja, nenhuma classe pode herdar de uma classe declarada como final.

Tornar uma classe final pode ser necessário, por exemplo, para atender a requisitos de segurança, impedindo que programadores criem subclasses que poderiam “driblar” restrições de segurança.

Já atributos declarados como final se comportam como constantes e devem ser iniciados na declaração ou no construtor da classe, não podendo ser reescritos posteriormente.

Page 69: Oswaldo Poo

Classes e métodos final

Exemplos:private final int fator = 2;

// atributo finalprotected final void abrir();

// metodo finalpublic class conta {

// classe final...

}

Page 70: Oswaldo Poo

Revendo a aplicação

Para consolidar os conceitos de classe abstrata, método abstrato, sobrecarga de método, polimorfismo de método, operador this e operador final, vamos alterar a aplicação que fizemos na aula passada para o código que se segue.

Primeiramente, vamos adicionar a classe abstrataEmpregado, que possui apenas três atributos (nome, sobrenome e cpf). Essa classe impede que classes derivadas alterem os métodos set desses atributos (uso do final) e usa sobrecarga de nomes para receber argumentos no construtor com os mesmos nomes dos atributos (uso do this):

Page 71: Oswaldo Poo

Revendo a aplicação

//Classe Empregado public abstract class Empregado extends Object {

protected String nome;protected String sobrenome;protected String cpf;public Empregado (// Construtor com 3 argumentos

String nome, String sobrenome, String cpf){this.nome = nome; // uso do operador thisthis.sobrenome = sobrenome;this.cpf = cpf;

} public final void setNome (String nome){//usa final

this.nome = nome;}public String getNome() {

return nome;}

Page 72: Oswaldo Poo

Revendo a aplicação

public final void setSobrenome (String sobrenome){this.sobrenome = sobrenome;

}public String getSobrenome() {

return sobrenome;}public final void setCpf (String cpf){

this.cpf = cpf;}public String getCpf() {

return cpf;}public abstract double salario(); // Método abstrato

} // fim da classe Empregado

Page 73: Oswaldo Poo

Revendo a aplicação

A seguir vamos reescrever a classe EmpComissionado para herdar da classe abstrata Empregado, fazendo as adaptações necessárias no construtor.

//Classe Empregado Comissionadopublic class EmpComissionado extends Empregado {

protected double totalVendas;protected double taxaComissao;protected double bonus;

public EmpComissionado (String nome,String sobrenome, String cpf, double totalVendas,double taxaComissao, double bonus){

// chama construtor da classe abstratasuper (nome, sobrenome, cpf);setTotalVendas (totalVendas);setTaxaComissao (taxaComissao);setBonus(bonus);

}

Page 74: Oswaldo Poo

Revendo a aplicação

public void setTotalVendas (double totalVendas){this.totalVendas =

(totalVendas < 0.0) ? 0.0 : totalVendas;}public double getTotalVendas () {

return totalVendas;}public void setTaxaComissao (double taxaComissao){

this.taxaComissao = (taxaComissao < 0.0) ? 0.0 : taxaComissao;

}public double getTaxaComissao () {

return taxaComissao;}public void setBonus (double bonus){

this.bonus = (bonus < 0.0) ? 0.0 : bonus;}

Page 75: Oswaldo Poo

Revendo a aplicação

public double getBonus (){return bonus;

}public double salario(){ // Calcula o salário

return (taxaComissao * totalVendas + getBonus() * 2 * taxaComissao * totalVendas);

}public String toString () {

return String.format ("%s%s %s\n%s%s\n%s%.2f\n%s%.2f\n%s%.2f","Identificacao: ", nome, sobrenome,"CPF: ", cpf,"Total de vendas: ", totalVendas,"Taxa de comissão: ", taxaComissao,"Salario total: ", salario() );

}} // fim da classe Empregado Comissionado

Page 76: Oswaldo Poo

Revendo a aplicação

A classe EmpFixoComissionado continua herdando da classe EmpComissionado. Só sofreu alteração nos métodos toString() e salario() que agora contemplam o proposto no desafio da aula passada:

//Classe Empregado com salário base mais Comissãopublic class EmpFixoComissionado extends EmpComissionado {

private double salarioBase; // atributo exclusivo// Construtor com 7 argumentos public EmpFixoComissionado ( String nome,String sobrenome, String cpf, double totalVendas,double taxaComissao, double salarioBase,double bonus){

// chama construtor da superclasse EmpComissionadosuper (nome, sobrenome, cpf, totalVendas,

taxaComissao,bonus);// inicia atributo próprio da classesetSalarioBase (salarioBase);

}

Page 77: Oswaldo Poo

Revendo a aplicação

public void setSalarioBase (double salarioBase){this.salarioBase = (salarioBase < 0.0) ? 0.0 : salarioBase;

}public double getSalarioBase() {

return salarioBase;}public double salario(){ // Calcula o salário

return (salarioBase + taxaComissao * totalVendas + getBonus() * taxaComissao * totalVendas);

}public String toString () {

return String.format ("%s%s %s\n%s%s\n%s%.2f\n%s%.2f\n%s%.2f\n%s%.2f", "Identificacao: ", nome, sobrenome,

"CPF: ", cpf, "Total de vendas: ", totalVendas, "Taxa de comissão: ", taxaComissao, "Salario base: ", salarioBase, "Salario total: ", salario() );

}} // fim da classe Empregado Fixo Comissionado

Page 78: Oswaldo Poo

Revendo a aplicação

A nova classe EmpAssalariado herda diretamente da classe abstrata://Classe Empregado Assalariadopublic class EmpAssalariado extends Empregado {

private double salarioMensal; // atributo exclusivo// Construtor com 4 argumentos public EmpAssalariado (String nome,

String sobrenome, String cpf,double salarioMensal){

// chama construtor da classe abstratasuper (nome, sobrenome, cpf); setSalarioMensal(salarioMensal);

} public void setSalarioMensal (double salarioMensal){

this.salarioMensal = salarioMensal;}public double getSalarioMensal(){

return salarioMensal;}

Page 79: Oswaldo Poo

Revendo a aplicação

public double salario(){ // Salário sem abonoreturn (getSalarioMensal());

}public double salario(double abono){ //sal. c/ abono

return (getSalarioMensal());}public String toString () {

return String.format ("%s%s %s\n%s%s\n%s%.2f\n%s%.2f\n","Identificacao: ", nome, sobrenome,"CPF: ", cpf, "Salario total: ", salario(),"Salario total com abono: ", salario(100.0));

}} // fim da classe Empregado Assalariado

Page 80: Oswaldo Poo

Revendo a aplicação

Finalmente, o código de teste (classe Principal) fica como se segue (agora só está imprimindo chamando o método toString das classes):

public class Principal{ public static void main ( String argv[]) {

EmpFixoComissionado empregadoFC =new EmpFixoComissionado ("Roberto", "Silveira",

"123456789-10", 10000, 0.02, 300, 0.01);EmpComissionado empregadoC =

new EmpComissionado ("Francisco", "Oliveira","987654321-00", 20000, 0.02, 0.01);

EmpAssalariado empregadoA =new EmpAssalariado ("Joaquim", "Alberto",

"192837465-99", 1000); System.out.printf ("\n%s: \n\n%s\n\n",

"Informacoes do empregado comissionado:",empregadoC.toString() );

Page 81: Oswaldo Poo

Revendo a aplicação

System.out.printf ("\n%s: \n\n%s\n\n", "Informacoes do empregado fixo comissionado:", empregadoFC.toString() );

System.out.printf ("\n%s: \n\n%s\n\n", "Informacoes do empregado assalariado:", empregadoA.toString() );

} // fim do método main} // fim da classe Principal

Compile e execute o código acima.

Page 82: Oswaldo Poo

Desafios

1. Altere o código da classe de teste (Principal) para que o empregado assalariado (objeto empregadoA) seja declarado como da classe estática Empregado mas continue sendo instanciado como da classe EmpAssalariado. Execute e veja que funciona perfeitamente o polimorfismo de métodos.

2. Agora tente alterar também a classe de instanciação do objeto empregadoA para Empregado. Compile e explique a ocorrência de erro.

3. Atendendo ao diagrama de classes da página dois desta aula, implemente também a classe EmpHorista. Crie os métodos e atributos que julgar necessários para que os objetos desta classe tenham um comportamento semelhante aos objetos das demais classes do projeto. Altere a classe Principal para que esta instancie e teste também um objeto empregadoHorista, imprimindo suas informações, inclusive seu salário, que deve ser calculado com base em um valor constante (use um atributo final) representativo do valor da hora trabalhada, multiplicado pelo número de horas trabalhadas (um atributo exclusivo desta classe).

Page 83: Oswaldo Poo

Aula 05 - Objetivos

l Reforçar o conceito de polimorfismo de método

l Criar arrays de objetosl Trabalhar com vinculação dinâmical Aprender a utilizar polimorfismo de interface

Page 84: Oswaldo Poo

Recordando...

Na aula passada, empregando o conceito de herança, criamos uma superclasse abstrata Empregado, da qual derivavam três subclasses EmpComissionado, EmpAssalariado e EmpHorista(esta última, no desafio). Vimos como declarar um objeto como sendo estaticamente de uma superclasse, mas instanciá-lo dinamicamente de uma subclasse. Hoje vamos criar uma array de objetos distintos usando a técnica de herança e tratar seus métodos de forma polimórfica.

Page 85: Oswaldo Poo

Declarando um array de empregados

Vejamos, primeiramente, a declaração para criar um array de quatro empregados (veja que foi usada a superclasse abstrata Empregado):Empregado empregados[] = new Empregado[4];

Entretanto, a superclasse é abstrata e cada instanciação de objeto tem que ser de uma das subclasses não abstratas, como no exemplo abaixo:

empregados[2] = new EmpAssalariado ("Joaquim", "Alberto","192837465-99", 1000);

Para fazermos referência ao método salário, que foi sobreposto em cada uma das subclasses, podemos usar o polimorfismo de método:

empregados[i].salario();Entretanto, quando formos fazer referência a um método da classe derivada

que além de ter sido sobreposto (reescrito na subclasse) foi também sobrecarregado (foram criadas diferentes versões na subclasse passando diferentes quantidades de parâmetros), será necessária uma referência explicita àsubclasse, para que o compilador possa fazer a resolução da referência estática. Faremos isso através de um mecanismo chamado coerção explícita (casting). Com este mecanismo, é possível criar um objeto da subclasse e atribuir a ele a referência a um objeto da superclasse que tenha sido anteriormente criado. Desta forma, o compilador consegue compreender uma referência a um método que tenha sido sobrecarregado na subclasse.

Page 86: Oswaldo Poo

Fazendo uma coerção explícita

O Java permite a atribuição de uma referência de superclasse a uma variável de subclasse por meio de uma coerção (cast) explícita, técnica conhecida como downcasting. Vejamos como realizar o downcasting:

EmpAssalariado empAssalariado =(EmpAssalariado)empregados[j];

Isto foi necessário, pois desejamos poder chamar tanto o método salário(), sem parâmetros e que não exige casting, quanto o método salário(double abono), que foi sobrecarregado (e, portanto, não existe na superclasse).

Page 87: Oswaldo Poo

A implementação do array e do casting

Para realizar as implementações desejadas, só necessitamos mudar a classe EmpAssalariado (para que o método toString não mais chame o método salario com parâmetro de abono) e a classe de teste Principal.

public class Principal{ public static void main ( String argv[]) {

Empregado empregados[] = new Empregado[4];// arrayempregados[0] = new EmpFixoComissionado ("Carlos",

"Silva","123456789-10", 10000, 0.02, 300, 0.01);empregados[1] = new EmpComissionado ("Francisco",

"Matos","987654321-00", 20000, 0.02, 0.01);empregados[2] = new EmpAssalariado ("Joaquim",

"Alberto", "192837465-99", 1000);empregados[3] = new EmpHorista ("Felipe",

"Martins", "999888765-43", 100);

Page 88: Oswaldo Poo

A implementação do array e do casting

for ( int j = 0; j < empregados.length; j++ ){System.out.printf( "Empregado da classe %s \n",

empregados[j].getClass().getName()); System.out.println (empregados[j]); // toStringif ( empregados[j] instanceof EmpAssalariado ) {

EmpAssalariado empregadoA = (EmpAssalariado)empregados[j];

System.out.printf("Salario (com abono): R$ %.2f\n\n", empregadoA.salario(200));

} // fim do if} // fim do for

} // fim do método main} // fim da classe Principal

Page 89: Oswaldo Poo

A implementação do array e do casting

Na classe EmpAssalariado, só muda o método toString:public String toString () {

return String.format ("%s%s %s\n%s%s\n%s%.2f","Identificacao: ", nome, sobrenome,"CPF: ", cpf, "Salario Total: ", salario());

}A classe EmpHorista já foi acrescentada no desafio da aula passada://Classe Empregado Horistapublic class EmpHorista extends Empregado {

private final double valorHora = 7.50;protected double horasTrabalhadas;// Construtor com 4 argumentos public EmpHorista (String nome, String sobrenome,

String cpf, double horasTrabalhadas){super (nome, sobrenome, cpf); setHorasTrabalhadas(horasTrabalhadas);

}

Page 90: Oswaldo Poo

A implementação do array e do casting

public void setHorasTrabalhadas (doublehorasTrabalhadas){

this.horasTrabalhadas = horasTrabalhadas;}public double getHorasTrabalhadas(){

return horasTrabalhadas;} public double salario(){ // Calcula salário simples

return (getHorasTrabalhadas()*valorHora);}public String toString () {

return String.format ("%s%s %s\n%s%s\n%s%.2f\n","Identificacao: ", nome, sobrenome,"CPF: ", cpf, "Salario total: ", salario());

}} // fim da classe Empregado HoristaAs demais classes são iguais às da aula passada. Compile e teste.

Page 91: Oswaldo Poo

Alterando o for

Além da implementação utilizando o comando for “clássico” como visto acima, podemos alternativamente empregar o comando for estendido, disponível a partir do Java 5. Com ele, a implementação da classe Principal fica mais “elegante”, dispensando o uso de uma variável de controle e aproveitando a dimensão da declaração do tipo array. Veja:

for ( Empregado empregadoAtual : empregados ){System.out.printf( "Empregado da classe %s \n",

empregadoAtual.getClass().getName()); System.out.println (empregadoAtual); if (empregadoAtual instanceof EmpAssalariado ) {

EmpAssalariado empregadoA = (EmpAssalariado)System.out.printf(

"Salario (com abono): R$ %.2f\n\n", empregadoA.salario(200));

} // fim do if} // fim do for

Faça a alteração, compile e teste desta outra forma.

Page 92: Oswaldo Poo

Usando interfaces

Ainda no exemplo da aula passada, o que fizemos foi criar uma superclasse destinada apenas a definir o que é comum às subclasses dela derivadas, sem que se tenha a intenção de efetivamente instanciar objetos dessa classe, que é conhecida como classe abstrata.

Outra forma de conseguir esse resultado é criando uma Interface. Uma interface define um conjunto de métodos que uma classe deve implementar, mas não define como esses métodos devem ser implementados. É utilizada quando classes não relacionadas necessitam compartilhar métodos e constantes. Isto permite que instâncias de classes não relacionadas sejam processadas de forma polimórfica –respondam às mesmas chamadas de métodos.

O programador pode criar uma interface que descreve a funcionalidade desejada e então implementar essa interface em quaisquer classes que requerem essa funcionalidade.

Utiliza-se uma interface no lugar de uma classe abstrata quando não hánenhuma implementação padrão a herdar – nenhum atributo (variável de classe) e nenhum método com implementação. Uma interface é, essencialmente, uma coleção de constantes e métodos abstratos. Métodos em uma interface são sempre públicos e abstratos. Constantes em uma interface são sempre públicas, estáticas e final.

A interface resolve o problema de Java não suportar herança múltipla como outras linguagens (C++, por exemplo), de forma mais elegante, pois apenas relacionaas funcionalidades necessárias às classes.

Page 93: Oswaldo Poo

Usando interfaces

No nosso exemplo, se encararmos o salário a ser pago a um empregado como uma despesa, podemos observar que outras classes não relacionadas a empregados podem também representar despesas.

Por exemplo, uma fatura é uma despesa e poderíamos criar uma interface Pagamento, que fosse comum às faturas e aos empregados, na qual houvesse um método para calcular o pagamento. Embora aplicado a coisas não relacionadas (faturas e empregados), o método tem a ver com obter algum valor a ser pago.

A modelagem do sistema teria agora o aspecto da figura ao lado.

Como já vimos, em Java as classes sópodem ter uma superclasse pois Java não suporta herança múltipla. Em contraposição, uma classe pode implementar várias interfaces além de herdar de uma classe. Exemplo:

public class Testa implements Interface1, Interface2, interface3 extends SuperClasse

Page 94: Oswaldo Poo

Revendo a aplicação

Para consolidar os conceitos de arrays de objetos, castingde classes e criação de interfaces, vamos alterar a aplicação que fizemos na aula passada para o código que se segue.

A interface Pagamento possui uma sintaxe que apenas declara os métodos que serão implementados pelas classes que implementem esta interface. No nosso caso, como já dissemos, apenas um método para calcular o pagamento a ser feito para os empregados e as faturas. O código será apenas:

public interface Pagamento{double calcularPagamento();

}

Page 95: Oswaldo Poo

Revendo a aplicação

A classe Fatura possui atributos para guardar o nome da peça, o seu preçoe a sua quantidade. Além disso, implementa o método para calcular o pagamentoque foi previsto na interface. Seu código está relacionado a seguir:

public class Fatura implements Pagamento{

private String nome; // nome da peçaprivate int quantidade; // quantidade de peçasprivate double preco; // preço unitário da peçapublic Fatura (String nome, int quantidade, double preco){

this.nome = nome;this.setQuantidade (quantidade); this.setPreco (preco);

} public void setNome(String nome){

this.nome = nome; }

Page 96: Oswaldo Poo

Revendo a aplicação

public String getNome() {return nome;

} public void setQuantidade(int quantidade){

this.quantidade = (quantidade<0)? 0 : quantidade; } public int getQuantidade() {

return quantidade;} public void setPreco(double preco) {

this.preco = ( preco < 0.0 ) ? 0.0 : preco; } public double getPreco() {

return preco;

}

Page 97: Oswaldo Poo

Revendo a aplicação

public String toString() {return String.format(

"%s: \n%s: %s \n%s: %d \n%s: R$ %.2f", "Fatura", "Nome da Peça", getNome(), "Quantidade",

getQuantidade(), "Preço por item", getPreco() );} public double calcularPagamento () {

return getQuantidade() * getPreco(); }

} // fim da classe Fatura

Page 98: Oswaldo Poo

Revendo a aplicação

Na classe Empregado mudaremos apenas a declaração da classe para:public abstract class Empregado implements Pagamento {

Nas demais classes de empregados, acrescentaremos um implementação do método calcularPagamento() que apenas chama o método salário(). Coloque em cada um dos arquivos das classes:

public double calcularPagamento () { return salario();

}A classe de teste Principal, agora instancia cinco elementos em um array de objetos com a mesma interface (Pagamento). Quatro desses objetos são empregados e um é uma fatura. Veja o código usando o comando for estendido:

public class Principal{ // Testando o projetopublic static void main ( String argv[]) {

Pagamento pagamentos[] = new Pagamento[5];// arraypagamentos[0] = new EmpFixoComissionado ("Carlos",

"Silva","123456789-10", 10000, 0.02, 300, 0.01);

Page 99: Oswaldo Poo

Revendo a aplicação

pagamentos[1] = new EmpComissionado ("Francisco","Matos","987654321-00", 20000, 0.02, 0.01);

pagamentos[2] = new EmpAssalariado ("Joaquim","Alberto", "192837465-99", 1000);

pagamentos[3] = new EmpHorista ("Felipe","Martins", "999888765-43", 100);

pagamentos[4] = new Fatura ("Guardanapo",10,1.20); for (Pagamento pagamentoCorrente : pagamentos){

if (pagamentoCorrente instanceof Empregado) {System.out.printf ("%s\n","Empregado:");

}System.out.println(pagamentoCorrente);//toStringSystem.out.printf("Pagamento: R$ %.2f\n\n",

pagamentoCorrente.calcularPagamento());} // fim do for

} // fim do método main} // fim da classe PrincipalCompile e execute os códigos das classes acima.

Page 100: Oswaldo Poo

Desafios

1. Coloque na interface um atributo imposto, no valor de 10%, que deve ser aplicado no cálculo do pagamento de todas as classes. Ou seja, o método calcularPagamento deve acrescer o percentual de imposto ao valor a ser pago.

2. Observe o modelo abaixo:

Page 101: Oswaldo Poo

Desafios

Implemente as classes obedecendo à hierarquia do diagrama. A interface define o método para calcular pontos, que é especificamente implementado em cada classe, obedecendo às seguintes regras de negócio:

– Pontos de um cartão de prova são: o número de acertos multiplicado por dois, menos o número de erros;

– Pontos de um clube de futebol são o número de vitórias multiplicado por três, mais o número de empates;

– Pontos de um clube de investimentos são o número de sócios multiplicado pelo investimento médio. A classe de teste deve criar um array de três objetos, instanciando

um objeto de cada classe passando os parâmetros adequados ao construtor. A seguir, deve enviar uma mensagem ao objeto pedindopara que este calcule a quantidade de pontos e deve imprimir esse valor recebido.

Page 102: Oswaldo Poo

Aula 06 - Objetivos

l Diferenciar tipos primitivos de dados e tipos de referência a objetos

l Entender o uso dos operadores aritméticos, lógicos e relacionais

l Aprender a sintaxe e semântica das estruturas de controle de fluxo

l Tratar entradas de dados

Page 103: Oswaldo Poo

Recordando...

Nas aulas passadas, criamos algumas aplicações Java para ilustrar os conceitos de POO apresentados. Nestas aplicações usamos variáveis de diversos tipos, operadores e alguns comandos de decisão e repetição. Hoje veremos esses tipos e comandos detalhadamente. Também veremos como ler dados do teclado, pois até agora sóimprimimos dados.

Page 104: Oswaldo Poo

Tipos primitivos e tipos de referência

Em Java, trabalhamos com dois tipos de dados: primitivos e de referência, estes também denominados como não primitivos. Primitivos:

4,94 X 10-324 a 1,70 X 1030864double

1,40 X 10-45 a 3,40 X 103832float

(-263 a 263-1 )64long

–2.147.483.648 até 2.147.483.647 (-231 a 231-1 )32int

–32768 até 32767 ( -215 a 215-1 )16short

‘\u0000’ a ‘\uFFFF’ (0 a 65535)16char

–128 até 127 ( -27 a 27-1 )8byte

True ou False1boolean

Valores armazenáveis na variávelQuant. BitsTipo

Page 105: Oswaldo Poo

Tipos primitivos e tipos de referência

Uma variável de tipo primitivo pode armazenar exatamente um valor do seu tipo declarado. Variáveis de tipo de referência são utilizadas para armazenar as localizações de objetos na memória do computador. Diz-se que estas variáveis referenciam objetos.

Os atributos de tipo primitivo são iniciados por ocasião da instanciação do objeto. Os atributos de tipos byte, char, short, int, long, float e double são iniciadas com zero, as variáveis do tipo boolean com false. Podem ser especificados valores iniciais para variáveis destes tipos quando de sua declaração. Variáveis locais de métodos não são iniciadas automaticamente.

As variáveis de instância de tipo de referência são iniciadas por padrão com o valor null – palavra reservada que representa uma “referência a nada”. Somente depois que o objeto é instanciado é que a variável contém uma referência para o objeto. Por exemplo, o comando

Curso meuCurso = new Curso();cria uma instância (objeto) da classe Curso, e a variável meuCurso contém uma referência a esse objeto. A partir de então, a variável pode ser usada para chamar métodos do objeto ou referenciar seus atributos.

Page 106: Oswaldo Poo

Usando Operadores

O Java oferece um conjunto amplo de operadores aritméticos, relacionais e lógicos. Veja a tabela abaixo:

a||bOU lógico||

!aNegação!a&&bE lógico&&Lógicos

a<=bMenor ou igual<=a>bMaior que>

a<bMenor que<a!=bDiferente!=

a>=bMaior ou igual>=a==bIgual==Relacionais

--a ou a--Decremento unário--a/bDivisão/

++a ou a++Incremento unário++a*bMultiplicação*

-aMenos unário-a-bSubtração-

a%bResto da divisão%a+bAdição+Aritméticos

Ex. SignificadoOp.Ex.SignificadoOp.Tipo

Page 107: Oswaldo Poo

Estruturas de Controle do fluxo

Java contém três tipos de estruturas de controle(instruções): seqüência, seleção e repetição. Um programa é formado pela combinação destas estruturas, de forma a implementar o que o algoritmo determina.

A estrutura de seqüência permite aglutinar vários comandos em um bloco de comandos delimitado por chaves ({...}). Isto deve ser feito sempre que queiramos delimitar os comandos que façam parte de uma outra estrutura de controle de decisão ou repetição (if/else, switch, for, while, etc.).

Page 108: Oswaldo Poo

Instruções de seleção

Comando ifO if é uma instrução que permite a seleção entre dois caminhos distintos, conforme a

avaliação de uma condição lógica como falsa ou verdadeira.If (expressão lógica)comando1; else comando2; Exemplo:If ( nota >= 6 )

System.out. println (“Aprovado”);else

System.out. println (“Reprovado”);A parte do else é opcional. Comando1 e Comando2 podem ser blocos de comandos.

O compilador Java sempre associa um else à instrução if imediatamente anterior, a menos que instruído de outro modo pela colocação das chaves

Operador condicional ternárioComo já vimos em aulas anteriores, em algumas situações podemos usar o operador

“?”, que realiza a mesma operação do comando if. Ex:System.out.println(nota > 6 ? “Aprovado”:“Reprovado”);

Page 109: Oswaldo Poo

Instruções de seleção

Comando switchEste comando equivale a um conjunto de if encadeados:switch (expressão ordinal) {

case ordinal1: comando1; break;case ordinal2: comando2; break;case ordinalN: comandoN; break;default: comandoDefault;

}Exemplo:switch (opcao) {

case ‘a’:case ‘A’: System.out.println(“letra A”);

break;case ‘b’: case ‘B’: System.out.println(“letra B”);

break;default: System.out.println(“letra invalida”);

}

Page 110: Oswaldo Poo

Estruturas de repetição

Comando forO comando for é indicado para repetirmos um trecho de código uma

quantidade fixa de vezes. Sua sintaxe possui três seções opcionais:for (seção1; seção2; seção3) comando;

a seção1 é executada apenas uma vez e geralmente é usada para iniciar uma variável de controle do for. A seção2 é executada antes de cada iteração do for e habilita a execução de mais uma iteração, caso verdadeira (true). Geralmente éusada para testar a variável de controle do for. A seção3 é executada ao final de cada iteração do for e geralmente é usada para incrementar a variável de controle.

Exemplo:for (int i = 0; i < 4;i++)

System.out.printf(“%d ”,i); //imprime de 0 a 3 Comandos while / do

O comando while é indicado quando desejamos repetir um trecho de código uma quantidade indefinida de vezes, enquanto uma determinada condição for verdadeira. Sintaxe:

while (expressão lógica)comando1;

Page 111: Oswaldo Poo

Estruturas de repetição

Exemplo:while ( produto <= 100 )

produto = 3 * produto;

Caso a condição seja inicialmente falsa, nenhuma iteração será executada. Nos casos em que desejamos executar pelo menos uma vez os comando da repetição, devemos usar o comando do / while, Cuja sintaxe é a que se segue:

docomando1;

while (expressão lógica);Veja o exemplo:do

produto = 3 * produto;while ( produto <= 100 );// testa após ter executado

// pelo menos uma vez

Page 112: Oswaldo Poo

Lendo valores do teclado

Até agora, nossas aplicações apenas escreviam valores na tela de console. Fizemos isso usando (embora sem ter sido ainda explicado) um Stream de dados. Um Stream é um canal que conduz os dados de um lugar (um arquivo ou um dispositivo) para outro. A stream de saída padrão (out) está na classe Java.lang.System e é aberta automaticamente pela máquina virtual Java, já associada ao dispositivo de saída padrão (display).

Já a stream de entrada padrão (in), disponível estaticamente através da mesma classe Java.lang.System, é de utilização bastante precária, na medida em que disponibiliza métodos apenas de acesso a bytes, de forma que, para que se leia valores inteiros, reais ou strings, énecessário ir concatenando bytes para formar a entrada desejada. Assim, não utilizaremos essa forma de entrada e sim uma classe mais elaborada, disponível na biblioteca java.util.Scanner, que permite a chamada de métodos para ler diretamente strings, números inteiros e números reais.

Page 113: Oswaldo Poo

Lendo valores do teclado

Para utilizá-la, é necessário instanciar um objeto da classe Scanner e chamar um método apropriado para ler cada um dos tipos básicos ou String de um dispositivo qualquer. Por exemplo, para ler do dispositivo padrão de entrada, podemos ter o seguinte código:

// cria Scanner para ler entrada na janela de comandoScanner entrada = new Scanner( System.in );

// faz Scanner ler variáveis de diferentes tipospalavra = entrada.next() // lê String até <branco>nome = entrada.nextLine() // lê String até <ENTER>valorI = entrada.nextInt() // lê valor inteiro valorF = entrada.nextFloat() // lê valor floatvalorD = entrada.nextDouble() // lê valor doublevalorB = entrada.nextBoolean() // lê valor boolean

Além de ler os valores, podemos também testar se o valor é do tipo esperado, através de métodos que retornam valores lógicos. Por exemplo:

if (entrada.hasInt()) { // true, se entrada inteiraif (entrada.hasFloat()) { // true, se entrada floatif (entrada.hasDouble()) { // true, se entrada doubleif (entrada.hasBoolean()) { // true,se entrada boolean

Page 114: Oswaldo Poo

Aplicando os conceitos aprendidos

Para consolidar os conceitos de operadores, estruturas de controle e criação de interfaces, vamos criar uma aplicação diferente da que vínhamos fazendo nas aulas passadas. Nossa aplicação possuirá apenas uma classe (Curso), que guardará seu próprio nome, o nome de um aluno e as notas das três avaliações desse aluno no curso. A classe oferece métodos de get e set para seus atributos e um método que avalia se o aluno foi aprovado ou reprovado, de acordo com as notas das avaliações, retornando um String com essa avaliação final. Para julgar se o aluno foi aprovado, é feita a média das duas maiores notas e o aluno estará aprovado se esta for maior ou igual a 6,0.

public class Curso {private String nomeCurso;private String nomeAluno;private float notas[];

public Curso(String nomeCurso,String nomeAluno) {this.nomeCurso = nomeCurso;this.nomeAluno = nomeAluno;notas = new float[3];

}

Page 115: Oswaldo Poo

Aplicando os conceitos aprendidos

public void setNomeCurso( String nomeCurso ) {this.nomeCurso = nomeCurso;

}

public String getNomeCurso() {return nomeCurso;

}public void setNomeAluno( String nomeAluno ) {

this.nomeAluno = nomeAluno; }

public String getNomeAluno() {return nomeAluno;

}public void setNotas (float nota, int posicao){

notas[posicao] = nota;}

Page 116: Oswaldo Poo

Aplicando os conceitos aprendidos

public float calcularMedia() {int indNota=0; // indice das notasfloat piorNota=11; // valor da nota a descartar int indPiorNota=0; // indice da nota a descartar while ( indNota < 3 ) { // descobre a pior nota if (notas[indNota] < piorNota){

piorNota = notas[indNota];indPiorNota = indNota;

}indNota++;

} // fim do whileswitch (indPiorNota){//media das 2 melhores

case 0: return ((notas[1]+notas[2])/2);case 1: return ((notas[0]+notas[2])/2);case 2: return ((notas[0]+notas[1])/2);

} return 0;

} // fim do método calcularMedia

Page 117: Oswaldo Poo

Aplicando os conceitos aprendidos

public String determinarSituacao() {String situacao;if (calcularMedia() >= 6.0)

situacao = "APROVADO(A)";else

situacao = "REPROVADO(A)";return String.format("\n%s %s %s %s %s %s %s %.2f\n\n","O(a) aluno(a)",getNomeAluno(),"foi",situacao,"no curso",getNomeCurso(),"com media",calcularMedia());

} // fim do método determinarSituacao

} // fim da classe LivroNotas

Page 118: Oswaldo Poo

Aplicando os conceitos aprendidosA classe da aplicação de teste possui o seguinte código:import java.util.Scanner; // Classe Scannerpublic class AppCurso{

public static void main( String args[] ) {float nota;String curso="",aluno=""; //inicia StringsScanner entrada = new Scanner( System.in ); // cria Scanner p/ ler do console

System.out.printf("\nEntre com nome do curso: ");curso = entrada.nextLine();System.out.printf("\nEntre com nome do aluno: "); aluno = entrada.nextLine();Curso meuCurso = new Curso(curso,aluno);for (int cont=0; cont<3; cont++){System.out.printf("\nDigite a nota %d: ",cont+1); nota = entrada.nextFloat(); meuCurso.setNotas(nota,cont);

}System.out.printf("%s", meuCurso.determinarSituacao());

} // fim de main} // fim da classe AppCursoCompile e execute os códigos das classes acima.

Page 119: Oswaldo Poo

Desafios

1. Coloque na classe Curso um atributo frequencia, que represente o percentual de aulas assistidas pelo aluno. Modifique o método determinarSituacao para que considere um percentual mínimo de 75% para considerar o aluno aprovado.

2. Substitua o comando for da classe de teste pelo comando do/while

Page 120: Oswaldo Poo

Aula 07 - Objetivos

l Apresentar os operadores compostos de atribuição

l Usar os operadores unários de incremento e decremento

l Compreender o conceito e o uso de atributos e métodos Static

l Aprender a declarar e utilizar vetores e matrizes

l Reforçar a utilização da classe String

Page 121: Oswaldo Poo

Recordando...

Nas aulas passadas, criamos algumas aplicações Java em que instanciamos objetos a partir de classes que havíamos previamente declarado. Essas classes possuíam atributos que, após a instanciação dos objetos, eram tratados como variáveis de instância do objeto. Ou seja, cada atributo ou método era, atéagora, visto como um atributo ou método do objeto instanciado. Hoje veremos que os atributos e métodos podem pertencer somente à classe do objeto, sendo comuns aos diferentes objetosque tenham sido instanciados de uma mesma classe.

Antes, entretanto, vamos reforçar o conceito de operadores unários de incremento e decremento e de operadores compostos de atribuição.

Page 122: Oswaldo Poo

Operadores compostos de atribuição

A linguagem Java possui vários operadores compostos de atribuição para abreviar expressões de atribuição. Qualquer instrução na forma

variável = variável operador expressão;onde o operador seja +, -, *, / ou %, pode ser escrita na forma:

variável operador= expressão;Por exemplo, a instrução:

c = c + 3;pode ser abreviada com o operador composto de atribuição de adição: c += 3;Suponha:

int c = 3, d = 5, e = 4, f = 6, g = 12;+= c += 7 ou c = c + 7 resulta c = 10-= d -= 4 ou d = d – 4 resulta d = 1*= e *= 5 ou e = e * 5 resulta e = 20/= f /= 3 ou f = f / 3 resulta f = 2%= g %= 9 ou g = g % 9 resulta g = 3

Page 123: Oswaldo Poo

Operadores de Incremento e Decremento

Java tem dois operadores unários para adicionar 1 ou subtrair 1 de uma variável numérica – são o operador de incremento unário “++” e o operador de decremento unário “--". Um programa pode incrementar de 1 o valor de uma variável utilizando o operador de incremento, em vez das expressões “c = c+1” ou “c += 1”. Quando o operador de incremento ou decremento écolocado antes de uma variável é chamado operador de pré-incremento ou de pré-decremento, respectivamente. Quando é posto depois, échamado operador de pós-incremento ou pós-decremento.

Utiliza o valor atual na expressão e depoisdecrementa a de 1.

a--Pós-decremento

Decrementa a de 1 e depois utiliza o novo valor na expressão.

--aPré-decremento

Utiliza o valor atual na expressão e depoisincrementa a de 1.

a++Pós-incremento

Incrementa a de 1 e depois utiliza o novo valor

na expressão.

++aPré-incremento

Page 124: Oswaldo Poo

Operadores de Incremento e Decremento

A classe Incremento, a seguir, mostra as variações acima:

public class Incremento{public static void main( String args[] ) {int c = 5 , d = 5; // inicia variáveis com 5System.out.printf( "%d, %d, %d\n", c, c++, c ); System.out.printf( "%d, %d, %d\n", d, ++d, d );

} }

Page 125: Oswaldo Poo

Atributos static

Até o momento só havíamos aprendido como definir atributos de instância. Cada objeto tinha seus próprios atributos e uma modificação nos atributos de um objeto não afetava os atributos de outros objetos.

Neste tópico iremos apreender como definir atributos de classe. Esses atributos são os mesmos para todos os objetos de uma classe. Eles são, portanto, compartilhados pelos objetos. Uma mudança em um destes atributos é visível por todos os objetos instanciados dessa classe. Atributos de classe também são chamados de atributos static.

Para exemplificar, definiremos uma classe Robot que usa um atributo static como se fosse um contador, para saber quantosobjetos robots foram criados (instanciados).

Page 126: Oswaldo Poo

Atributos static

//Classe Robotclass Robot { public int x, y; // posição do robotpublic static int contador; //contador de instancias public Robot(int x,int y){ this.x = x; this.y = y; contador++; }

} A seguir a classe de teste Principal:class Principal { public static void main(String args[]) { Robot.contador=0; //inicializando variavel staticRobot r1,r2; System.out.println(Robot.contador); r1 = new Robot(10,12); System.out.println(Robot.contador); r2 = new Robot(11,13); System.out.println(Robot.contador);

} //main method } //class Principal Apesar de termos exemplificado com um inteiro, você poderia ter usado uma classe no lugar desse

atributo, naturalmente tomando o cuidado de chamar new antes de usá-lo.

Page 127: Oswaldo Poo

Métodos static

Métodos static também são chamados de métodos de classes. Estes métodos só podem operar sobre atributos que também sejam static. Assim:

public static void metodoA() {...Exemplificando, vamos criar um método static para

incrementar o contador:public static void incrementa(){

contador++;}

Não esqueça de alterar o construtor para, agora, chamar o novo método:

incrementa(); //substituindo o comando: contador++Após fazer as alterações, compile e teste.

Page 128: Oswaldo Poo

Vetores e matrizes

Em exemplos passados, já usamos vetores (arrays). Java dá suporte a vetores e matrizes de diversas formas. Por exemplo, podemos formar um vetor com as notas de cinco alunos de uma sala de aula:

float nota[] = { 6.5, 9.1, 4.2, 1.8, 6.4 };Neste caso nota[0] é a nota do primeiro aluno, isto é, 6.5, nota[1] é a nota

do segundo, ou seja, 9.1, e assim por diante.Para usarmos de vetores e matrizes precisamos cumprir três etapas:

1. Declarar o vetor ou a matriz. Para isto, declaramos o nome da variável e acrescentamos um par de colchetes antes ou depois. Por exemplo:

int compra[]; double mat[][],elemento[][][];int []nota;

Page 129: Oswaldo Poo

Vetores e matrizes

2. Reservar espaço de memória e definir o tamanho. É preciso definir o tamanho do vetor, isto é, a quantidade total de elementos que terá de armazenar. Em seguida é necessário reservar espaço de memória para armazenar os elementos. Isto é feito de maneira simples pelo operador new:

compra = new int[9]; // vetor de intnota = new double[35]; // vetor de doublemat = new float[20][30]; // matriz de float meusObjetos = new Object[10] // vetor de referências

3. Armazenar elementos no vetor ou matriz. Para armazenar uma informação em um dos elementos de um vetor ou matriz, é necessário fornecer um índice que indique a posição desse elemento. Por exemplo, para armazenar um valor na quarta posição do vetor nota, fazemos o seguinte:

nota[3] = 7.5;

Page 130: Oswaldo Poo

Vetores e matrizes

Os índices começam em zero e vão até o número de posições reservadas, menos um. No vetor nota, por exemplo, os índices válidos vão de 0 até 34. Ao tentar atribuir um valor a um elemento cujo índice esteja fora desse intervalo, ocorrerá um erro, impedindo a execução. Quando desejamos criar um vetor com valores atribuídos de modo estático podemos fazer como no primeiro exemplo acima, onde foi declarado um vetor nota e o mesmo já foi iniciado com as notas de cinco alunos. Veja mais exemplos:

// 12 primeiros termos da seqüência de Fibonacci:long fibonacci[] = {1,1,2,3,5,8,13,21,34,55,89,144};// Tabela de sen(n*pi/6), n=0,1,2,...5float seno[] = {0.000,0.500,0.866,1.000,0.866,0.500};// Tabela de log(1+n), n=0,2...99:double tlog[] = new double[100];for(int n=0; n<100; n++) tlog[i] = Math.log(1+n);// Matriz dos coeficientesdouble a[][] = { {1,2,3}, {0,1,3}, {0,0,-1} };

Page 131: Oswaldo Poo

Vetores e matrizes

Para exemplificar o uso de métodos/atributos estáticos e vetores, vamos alterar a classe Robot, criando um método static (guarda ()) para guardar, em um atributo static (o array robots[]), uma referência para cada robot instanciado. Teremos agora o seguinte código para a classe Robot:

class Robot { public int x, y; // posição do robotpublic static int contador; //contador de instanciaspublic static Robot robots[] = new Robot[10]; public Robot(int posicao, int x,int y){

this.x = x; this.y = y;incrementa();guarda(posicao,this);

}public int getX(){

return x;} public int getY(){

return y;}

Page 132: Oswaldo Poo

Vetores e matrizes

public void setX(int x){this.x = x;

} public void setY(int y){

this.y = y;}public static void incrementa(){

contador++;} public static void guarda (int posicao, Robot este){

robots[posicao] = este;}

}

Page 133: Oswaldo Poo

Vetores e matrizes

Agora, na classe Principal, após criar cada objeto robot, chamamos o método de cada objeto para pegar a sua respectiva posição, a partir das referências dos objetos que estão guardadas no array de objetos da classe Robot. Veja o código:

//Classe principalclass Principal {

public static void main(String args[]) { Robot.contador=0; //inicializando variavel staticRobot r; int i;for (i=0;i<10;i++) { // cria robots

r = new Robot(i,i*2,i*2); }for (i=0;i<10;i++) { // imprime posicoes

System.out.printf("Posicao do robot %d: x=%d y=%d\n",i,

Robot.robots[i].getX(),Robot.robots[i].getY());}

} //main method} //class PrincipalCompile e teste o programa acima.

Page 134: Oswaldo Poo

A classe String

A classe String fornece construtores para iniciar objetos String de várias maneiras. Quatro delas são mostradas no módulo main da classe abaixo.

public class StringConstructors{public static void main( String args[] ) {

char cArray[]={'b','i','r','t','h',' ','d','a','y'};String s = new String( "hello" );String s1 = new String(); String s2 = new String(s); String s3 = new String(cArray ); String s4 = new String(cArray, 6, 3 );System.out.printf(

"s1 = %s\ns2 = %s\ns3 = %s\ns4 = %s\n", s1, s2, s3, s4 ); // exibe strings

} // fim de main}

Page 135: Oswaldo Poo

A classe String

Alguns métodos da classe String:

length() – retorna o comprimento de uma string

public int length()

charAt(índice) – retorna o caractere de uma localização específica do string

public char charAt(int index)

getChars – retorna o conjunto de caracteres de um string como array char.

public void getChars(int srcBegin, int srcEnd,char[] dst, int dstBegin)

Page 136: Oswaldo Poo

A classe String

O funcionamento desses métodos é visto na classe Miscelanea a seguir:public class Miscelanea{

public static void main( String args[] ) {String s1 = "OTO AMA ANA";char charArray[] = new char[3];System.out.printf("O String s1: %s", s1 );System.out.printf("\nTamanho: %d",s1.length());// percorre s1 com charAt e exibe em ordem inversaSystem.out.print( "\nO String invertido: " );for ( int count=s1.length()-1; count>=0; count--)

System.out.printf( "%s", s1.charAt( count ));// copia caracteres do String para o charArrays1.getChars( 4, 7, charArray, 0 );System.out.print("\Caracteres de 4 ate 6: " );for (char caracter : charArray )

System.out.print( caracter ); System.out.println();} // fim de main

}

Page 137: Oswaldo Poo

Desafio

Crie uma classe Disciplina que possua nomes da matéria e do professor. Deve haver um array (static) com todas as referências para os alunos da disciplina. A aplicação deve ler os nomes do professor e da matéria e instanciar um objeto da classe Disciplina com os valores lidos para os atributos. Em seguida, deve ler o nome de 10 diferentes alunos e, para cada aluno, instanciar um objeto de uma classe Aluno, que deve possuir, além do nome, uma nota (inicialmente 0). Ao instanciar o aluno, a aplicação deve guardar sua referência no vetor da classe Disciplina. Depois disso, a aplicação deve pedir um nome de aluno, procurar o objeto aluno que possui esse nome e alterar sua nota para um valor fornecido pelo usuário.

Page 138: Oswaldo Poo

Aula 08 - Objetivos

l Reforçar conceitos sobre arraysunidimensionais e multidimensionais

l Passar arrays como argumentos de métodos l Entender o conceito de coleções e aprender a

usar a classe Arraysl Aprender a criar pacotes de classes l Introduzir o conceito de interfaces gráficas

(GUI)l Apresentar componentes Swing

Page 139: Oswaldo Poo

Recordando...

Em aulas passadas, vimos como declarar, instanciar e iniciar arrays de uma ou mais dimensões, de diferentes formas. Recorde algumas delas:

Instanciar um arraybidimensional c/ linhas de tamanhos diferentes

int n [ ] [ ]; n = new int [2] [ ]; n[0]=new int[3];n[1]=new int[5];

Instanciar e iniciar com valores um arraybidimensional (matriz)

int m [ ] [ ]; m=new int [2][3];m[0]={1,3,5}; m[1]={7,9,0};

int m [ ] [ ] = {{1,3,5}{7,9,0}};

Instanciar e iniciar um array com valores

k[0]=2; k[1]=4; k[2]=6;k[3]=8; k[4]=10;

int k[ ] = {2, 4, 6, 8, 10};

Instanciar dois arraysfloat a [ ]; float b [ ];float [ ] a, b;

Instanciar um arrayint c[ ]; c = new int[10];int c[ ]=new int [10];

O que está sendo feitoFormas alternativas de fazer

Page 140: Oswaldo Poo

Passando arrays como argumentos de métodos

Para passar um array como argumento para um método, especifique o nome do array sem colchetes. Por ex., para uma array declarado como:

int valor[] = int[10]

A chamada de um método trataValor que recebesse esse array, seria:trataValores(valor);

Já a declaração do método com o argumento formal, teria a forma:void trataValores(int a[]);

Caso desejássemos passar apenas um elemento do array, faríamos:trataValor(valor[4]); //passa o quinto elemento

Neste caso, o método deveria ser declarado como: void trataValor(int b);

Page 141: Oswaldo Poo

Passando arrays como argumentos de métodos

Em muitas linguagens de programação, existem duas maneiras de passar argumentos em chamadas de métodos: passagem por valor e passagem por referência. Ao contrário dessas linguagens, O Java nãopermite escolher passar por valor ou por referência – todos os argumentos são passados por valor. Uma chamada de método pode passar dois tipos de valores para um método: as cópias de valoresprimitivos, int por exemplo, e as cópias de referências para objetos , inclusive referências a arrays. Objetos não podem ser passados para os métodos.

Quando um método modifica um parâmetro do tipo primitivo, as alterações no parâmetro não têm nenhum efeito no valor original do argumento no método chamador. Isto também é verdadeiro para os parâmetros de tipo por referência. Se o método chamado modificar um parâmetro de tipo por referência atribuindo a ele a referência a outro objeto, o parâmetro referenciará o novo objeto, mas a referência armazenada na variável do chamador ainda referencia o objeto original.

Page 142: Oswaldo Poo

ColeçõesPodemos armazenar vários objetos ou valores de tipos primitivos em um array e

manipular este array como sendo uma única entidade. Um array pode ser encapsulado em uma classe, possibilitando a criação de métodos específicos de manipulação do array encapsulado.

Apesar da flexibilidade que pode ser obtida com o encapsulamento de um array em uma classe, algumas necessidades úteis não podem ser implementadas de forma trivial ou eficiente. Como, por exemplo:

– o tamanho do array não pode ser modificado depois do array criado;– um array somente pode conter elementos de um único tipo, exceto se

considerarmos os mecanismos de herança e polimorfismo;– algumas operações não podem ser realizadas de maneira simples em array como

inserir e excluir um determinado elemento.A linguagem Java possui classes e interfaces que poupam trabalho e oferecem

mecanismos para agrupar e processar objetos em conjuntos, denominados genericamente como coleções. Muitas dessas classes implementam estruturas de dados complexas, mas cujo uso é transparente para o programador. Todas essas classes fazem parte do pacote java.util.

Resumindo, uma coleção é uma estrutura de dados, na realidade um objeto, que pode armazenar referências a outros objetos. Normalmente as coleções contêm referências a objetos que são todos do mesmo tipo. As interfaces de estrutura das coleções declaram as operações a serem realizadas nessas coleções: Collection, Set, List, Map, Queue, ....

Page 143: Oswaldo Poo

Classe Arrays

A classe Arrays fornece métodos static de alto nível para manipular arrays, como sort para ordenar o array, binarySearch para pesquisar o array ordenado, equals para comparar arrays e fill para colocar valores no array. O aplicativo a seguir mostra a utilização de alguns desses métodos:

import java.util.Arrays; // Classe Arraysimport java.util.Scanner; // Classe Scannerpublic class UsandoArrays {

private int intArray[] = { 1, 2, 3, 4, 5, 6 };private double doubleArray[] = {8.4,9.3,0.2,7.9,3.4};private int intArrayCheio[], intArrayCopia[];public UsandoArrays(){ //construtor

intArrayCheio = new int[10];intArrayCopia = new int[intArray.length];Arrays.fill (intArrayCheio, 7);// preenche com 7sArrays.sort (doubleArray); // ordena doubleArraySystem.arraycopy (intArray, 0, intArrayCopia, 0,

intArray.length );}

Page 144: Oswaldo Poo

Classe Arrays

public void mostraArrays() { System.out.print( "doubleArray ordenado: " );for (double doubleValue : doubleArray)

System.out.printf ("%.1f; ", doubleValue);System.out.print( "\nintArray: " );for ( int intValue : intArray )

System.out.printf( "%d ", intValue );System.out.print( "\nintArrayCheio: ");for ( int intValue : intArrayCheio )

System.out.printf( "%d ", intValue );System.out.print( "\nintArrayCopia: " );

for ( int intValue : intArrayCopia )System.out.printf( "%d ", intValue );

System.out.println( "\n" );}public int pesquisaInt( int value ){

return Arrays.binarySearch(intArray, value );}

Page 145: Oswaldo Poo

Classe Arrays

public void mostraIgualdade(){boolean b = Arrays.equals(intArray, intArrayCopia);System.out.printf("intArray %s intArrayCopia\n",

( b ? "==" : "!=" ));b = Arrays.equals( intArray, intArrayCheio );System.out.printf( "intArray %s intArrayCheio\n",

( b ? "==" : "!=" ) );} public static void main( String args[] ) {

UsandoArrays meuArray = new UsandoArrays();meuArray.mostraArrays();meuArray.mostraIgualdade();Scanner entrada = new Scanner( System.in );System.out.printf("\nEntre com valor a procurar: ");int val = entrada.nextInt();

Page 146: Oswaldo Poo

Classe Arrays

int location = meuArray.pesquisaInt(val);String lixo = entrada.nextLine() ;if ( location >= 0 )

System.out.printf("Valor %d encontrado na posicao %d do intArray\n",

val, location ); else

System.out.printf("Valor %d nao foi encontrado em intArray\n",val);

}}

Page 147: Oswaldo Poo

Criando Pacotes

Aplicações e projetos complexos necessitam de organização das classesque utilizam, de forma que fique claro a qual aplicação ou projeto as classes pertencem. Esta necessidade de organização é mais aparente quando se deseja compartilhar classes ou instalá-las em outro computador.

Java provê um mecanismo de agrupamento de classes em pacotes –packages – com o qual podemos criar grupos de classes relacionadas.

Para a criação desses pacotes, basta uma declaração de pertinência ao pacote em cada classe e a organização das classes em um diretório.

Para criar uma pacote basta, portanto, criar um diretório e colocar lá os códigos-fonte das classes que desejamos que façam parte desse pacote.

Como exemplo, vamos considerar as classes Data, Hora e, ainda, a classe DataHora que encapsula uma data e uma hora. Para aglutinar essas classes em um pacote, primeiramente devemos criar um diretório DataHora e, a seguir, armazenar as classes dentro desse diretório. Cada classe do pacote deve ter, no seu início, a palavra-chave package seguida do nome do diretório (pacote) ao qual a classe pertence. Veja para a classe Data:

Page 148: Oswaldo Poo

Criando Pacotes

package DataHora; // indica o pacote da classepublic class Data {

byte dia; // acessibilidade default é packagebyte mes; // acessibilidade default é package short ano; // acessibilidade default é packagepublic Data(byte d, byte m, short a){

dia = d; mes = m; ano = a;}public String toString(){

return dia + "/" + mes + "/" + ano;}

}

Page 149: Oswaldo Poo

Criando Pacotes

A seguir listamos a classe Hora que encapsula os dados de uma hora:

package DataHora; // indica o pacote da classepublic class Hora {

byte hora; // acessibilidade default é packagebyte minuto; // acessibilidade default é packagebyte segundo; // acessibilidade default é packagepublic Hora(byte h, byte m, byte s){

hora = h; minuto = m; segundo = s;}public String toString(){

return hora + ":" + minuto + ":" + segundo;}

}

Page 150: Oswaldo Poo

Criando Pacotes

A terceira classe do pacote DataHora é a classe de nome DataHora:

package DataHora;public class DataHora {

private Data novaData;private Hora novaHora; public DataHora(byte d, byte mes, short a, byte h,

byte min, byte s){novaData = new Data(d, mes, a);novaHora = new Hora(h, min, s);

}

Page 151: Oswaldo Poo

Criando Pacotes

public String toString(){String resulta = novaHora.hora + ":" +

novaHora.minuto + ":" + novaHora.segundo;resulta += " de " + novaData.dia + " de ";switch (novaData.mes){

case 1: resulta += "Janeiro"; break;case 2: resulta += "Fevereiro"; break;case 3: resulta += "Março"; break;case 4: resulta += "Abril"; break;case 5: resulta += "Maio"; break;case 6: resulta += "Junho"; break;case 7: resulta += "Julho"; break;case 8: resulta += "Agosto"; break;case 9: resulta += "Setembro"; break;case 10: resulta += "Outubro"; break;case 11: resulta += "Novembro"; break;case 12: resulta += "Dezembro"; break;

}

Page 152: Oswaldo Poo

Criando Pacotes

resulta += " de " + novaData.ano;return resulta;

}}Note que a classe DataHora acima, faz referência a atributos das classes Data e Hora (hora,

dia,etc.), que possuem acessibilidade default (package).As classes Data, Hora e DataHora pertencem ao pacote DataHora. A classe de teste

DemoDataHora utiliza as classes Data, Hora e DataHora , mas não faz parte do pacoteDataHora (coloque-a em outro diretório). Veja:

import DataHora.Hora;import DataHora.Data;import DataHora.DataHora;public class DemoDataHora {public static void main (String args[]){Hora meiodia=new Hora ((byte)12,(byte)00,(byte)00);Data hoje=new Data ((byte)24,(byte)10,(short)2006);DataHora agora=new DataHora ((byte)24,(byte)10,

(short)2006,(byte)19,(byte)50,(byte)00);System.out.println (meiodia); System.out.println (hoje); System.out.println (agora);

}}

Page 153: Oswaldo Poo

Usando interfaces gráficas

Até agora nossas aplicações utilizaram uma janela de texto (console) para entrada e saída de dados. A maioria dos aplicativos que utilizamos no dia-a-dia, entretanto, utiliza janelas com diversos recursos gráficos para interagir com o usuário, como campos de edição, botões e outros objetos gráficos que compõem o que se chama uma Interface Gráfica (GUI).

Uma GUI é construída a partir de componentes, também chamados de controles ou widgets (window gadgets) em outras linguagens. Um componente GUI é um objeto com o qual o usuário interage via mouse, teclado ou outro formulário de entrada. Exemplos de GUI são as janelas de aplicativos como o Internet Explorer, Word, etc,...

Page 154: Oswaldo Poo

Entrada e saída com JOptionPane

A classe JOptionPane do Java (pacote javax.swing) fornece caixas de diálogos pré-empacotadas tanto para entrada como para saída. Esses diálogos são exibidos invocando métodos JOptionPane static. A classe a seguir é um aplicativo de adição que utiliza dois diálogos de entrada para obter inteiros do usuário e um diálogo de mensagem para exibir a soma desses inteiros.

import javax.swing.JOptionPane; public class Adicao{ // Adição de inteiros

public static void main( String args[] ){String strNumero1 = JOptionPane.showInputDialog("Entre com um número" );String strNumero2 =JOptionPane.showInputDialog("Entre outro número");int numero1 = Integer.parseInt(strNumero1);int numero2 = Integer.parseInt(strNumero2);int soma = numero1 + numero2; //soma os númerosJOptionPane.showMessageDialog(null, "A soma é : " + soma,

"Soma de dois inteiros", JOptionPane.PLAIN_MESSAGE ); } // fim do main

} // fim da classe

Page 155: Oswaldo Poo

Entrada e saída com JOptionPane

O método showInputDialog da classe JOptionPane exibe um diálogo de entrada apresentando o argumento String para o usuário. Esse método devolve o String digitado na caixa de texto para o programa. Ao contrário da classe Scanner que pode “captar” valores de vários tipos através de seus métodos, o método showInputDialog sópermite “captar” informações do tipo String. Se usuário clicar no botão Cancel, o método retorna null. Se o usuário digitar uma informação não convertível para o tipo int, ou mesmo não digitar caracter algum, e clicar no botão OK, ocorrerá um erro em tempo de execução que, futuramente, veremos como tratar.

O aplicativo também utilizou o método showMessageDialog da classe JOptionPane para exibir uma mensagem que contém a soma dos dois números. O primeiro argumento informa a posição da caixa de diálogo na tela, no caso null indica que a caixa deve ficar no centro da tela. O segundo argumento é a mensagem a exibir, neste caso o resultado de uma concatenação. O terceiro argumento é um String que deve aparecer na barra de título da caixa de diálogo.

Page 156: Oswaldo Poo

Entrada e saída com JOptionPane

O quarto argumento é o tipo de diálogo:

Só a mensagem, sem ícone.PLAIN_MESSAGE

Apresenta um ícone verde com ?.QUESTION_MESSAGE

Apresenta um ícone amarelo com !.WARNING_MESSAGE

Apresenta um ícone azul com i.INFORMATION_MESSAGE

Apresenta um ícone vermelho com X.ERROR_MESSAGE

Page 157: Oswaldo Poo

Componentes Swing

A maioria dos aplicativos GUI exige interfaces mais elaboradas e personalizadas. Os componentes Swing são escritos, manipulados e exibidos em Java e fazem parte das Java Foundation Classes(JFC), que são bibliotecas para desenvolvimento de GUI para múltiplas plataformas. Abaixo, uma lista de componentes SwingGUI do pacote Javax.swing: Área para organizar componentes ou

desenho de imagens.JPanel

Lista de opções com possibilidade de digitação na caixa.

JComboBox

Lista de itens que permite seleção simples ou Múltipla.

JList

Especifica opções que podem ser selecionadas.

JCheckBox

Gera um evento ao clicar nele com o mouse.

JButton

Permite a digitação de um texto de entrada.

JTextField

Exibe texto não editável.JLabel

Page 158: Oswaldo Poo

Componentes Swing

Antes do conjunto Swing, introduzido no J2SE 1.2, as GUI eram construídas com componentes AWT ( Abstract Window Toolkit) do pacote java.awt. Estes componentes são exibidos de forma diferente em cada plataforma: Windows, Macintosh, ... A maneira como o usuário interage com um componente AWT particular também difere entre as plataformas. Juntas, a aparência e a maneira como o usuário interage com o aplicativo são conhecidas como a aparência e comportamento do aplicativo.

Componentes Swing permitem especificar uniformemente a aparência e o comportamento para um aplicativo em todas as plataformas ou utilizar a aparência e o comportamento personalizados de cada plataforma.

Entretanto, alguns componentes Swing requerem interação direta com o sistema local de janelas, o que pode restringir sua aparência e funcionalidade, sendo chamados de componentes Swing pesados. A maioria dos componentes Swing, entretanto, não são afetados pelos sistemas de janelas das plataformas e são componentes Swing leves.

Page 159: Oswaldo Poo

Componentes Swing

ObjectComponentContainerJComponentO diagrama UML ao lado, mostra a hierarquia da herança de classes a partir das quais os componentes Swing leves herdam seus atributos e comportamento comuns.A classe Object é a superclasse de toda a hierarquia de classes do Java. A classe Component (pacote java.awt) declara muitos dos atributos e comportamentos comuns aos componentes GUI em pacotes java.awt e javax.swing. A classe Container organiza e exibe outros objetos Container, assim como objetos Component, em tela. Qualquer objeto que é um Container pode ser utilizado para organizar outros objetos Component em uma GUI. Como um Container é um Component, é possível anexar Containers a outros Containers para ajudar na organização de uma GUI.A classe JComponent (pacote javax.swing) é a superclasse de todos os componentes leves Swing e declara seus atributos e comportamentos comuns. Como JComponent é uma subclasse de Container, todos os componentes Swing leves também são Containers.

Object

Component

Container

JComponent

Page 160: Oswaldo Poo

Criando aplicações GUI

O aplicativo a seguir introduz um framework, como é chamada, normalmente, a estrutura básica de uma interface. A maioria das janelas que são criadas são instâncias da classe JFrame ou um subclasse dela. JFrame fornece os atributos e comportamentos básicos de uma janela –barra de título e botões de minimizar, maximizar e fechar a janela. Em geral, uma aplicação GUI consiste de, pelo menos, duas classes: uma subclasse de JFrame e uma classe de aplicativo em que o método maincria e exibe a janela principal do aplicativo.

Uma interface típica com o usuário contém muitos componentes, o que poderia criar dificuldades para identificar o propósito de cada componente, a menos que sejam fornecidas informações que declaram o propósito de cada um deles. Para isso é usado um controle da classe JLabel, que é uma subclasse de JComponent. Um JLabel exibe uma única linha de texto de leitura, uma imagem, ou um texto com imagem.

Page 161: Oswaldo Poo

Criando aplicações GUI

A aplicação a seguir mostra vários recursos do componente JLabel e apresenta um exemplo de framework dado pelo gerenciador de layout FlowLayout. O Java tem vários gerenciadores de layout. Será utilizada uma instância da classe JFrame para exibir uma janela que contém 3 JLabel.

Ao construir uma GUI, cada componente deve ser anexado a um container.No caso deste aplicativo, uma janela criada com um JFrame. Geralmente pode ser especificada a posição de cada componente, o que é conhecido como especificar o layout dos componentes GUI. Nas próximas aulas estudaremos outros gerenciadores de layout do Java.

No FlowLayout, os componentes GUI são colocados em um container da esquerda para a direita, na ordem em que são anexados ao container pelo programa. Quando não houver mais espaço, eles continuam a aparecer da esquerda para a direita na próxima linha. Se o container for redimensionado, os componentes são reorganizados na nova largura do container, possivelmente com mais ou menos linhas de componentes.

setLayout(new FlowLayout());

Page 162: Oswaldo Poo

Criando aplicações GUI

A instrução acima, o método setLayout, herdado indiretamente da classe Container, especifica que o layout da janela será um FlowLayout. No caso é criado um objeto FlowLayout e passada sua referência como argumento para setLayout.

import java.awt.FlowLayout; // gerenciador de layoutimport javax.swing.JFrame; // janela básicaimport javax.swing.JLabel; // exibe textos e imagens import javax.swing.Icon; // para manipular imagensimport javax.swing.ImageIcon; // carrega imagensimport javax.swing.SwingConstants; //constantes do Swing public class UsaLabel extends JFrame{

private JLabel label1; // JLabel apenas com textoprivate JLabel label2; // JLabel com texto e íconeprivate JLabel label3; // texto e ícone adicionadospublic UsaLabel(){

super("Testando Labels");// frame básico c/ títulosetLayout(new FlowLayout()); // layout do framelabel1 = new JLabel("Label simples com texto" );label1.setToolTipText("Este é o label1");

Page 163: Oswaldo Poo

Criando aplicações GUI

add(label1); // adiciona label1 ao JFrameIcon bug = new ImageIcon(getClass().getResource("bug1.gif")); // string, Icon e alinhamento

label2 = new JLabel("Label com ícone à esquerda",bug,SwingConstants.LEFT);

label2.setToolTipText("Este é o label2");add(label2); // adiciona label2 ao JFramelabel3 = new JLabel(); // JLabel sem argumentoslabel3.setText("Label com ícone acima" ); //textolabel3.setIcon(bug); // adiciona o ícone label3.setHorizontalTextPosition(

SwingConstants.CENTER);label3.setVerticalTextPosition(

SwingConstants.BOTTOM);label3.setToolTipText("Este é o label3" );add(label3); // adiciona label3 ao JFrame

} // fim do construtor UsaLabel} // fim da classe

Page 164: Oswaldo Poo

Criando aplicações GUI

A classe TestaLabel, cria um objeto da classe LabelFrame e especifica a operação de fechamento padrão da janela (simplesmente a oculta). O método setDefaultCloseOperation da classe UsandoLabel, herdado de JFrame, com a constante JFrame.EXIT_ON_CLOSE como argumento, indica que o aplicativo termina quando a janela for fechada pelo usuário.

import javax.swing.JFrame;public class TestaLabel{

public static void main( String args[] ) { UsaLabel janela = new UsaLabel(); janela.setDefaultCloseOperation(

JFrame.EXIT_ON_CLOSE);janela.setSize(275,180);// larg.x alt. do framejanela.setVisible( true ); // exibe frame

} // fim de main} // fim da classe

Page 165: Oswaldo Poo

Desafio

1. Aumente a largura do Frame para compreender o funcionamento do estilo FlowLayout.

2. Procure informações sobre classes e métodos usados no docs do JDK.

3. Tente adicionar objetos JTextField e JButtonà janela criada explorando suas particularidades

Page 166: Oswaldo Poo

Aula 09 - Objetivos

l Reforçar conceitos sobre interfaces gráficas com componentes Swing

l Introduzir o conceito de eventol Apresentar mais alguns componentes Swingl Compreender o funcionamento do tratamento

de eventos

Page 167: Oswaldo Poo

Recordando...

Na aula passada, vimos como criar uma interface gráfica usando componentes do pacote Swing. Entretanto a aplicação que desenvolvemos somente exibia informações, não possuindo entrada de dados. Hoje vamos estender esse conceito, usando outros componentes típicos de aplicações gráficas, como botões e caixas de edição. Antes, entretanto, vamos desenvolver o conceito de tratamento de eventos.

Page 168: Oswaldo Poo

Tratamento de eventos

As tarefas que um aplicativo gráfico deve realizar são comandadas pelo usuário através da interação deste com a GUI. É comum clicar sobre um botão (“OK”, “Enviar” ou “Gravar”, por exemplo) para instruir o aplicativo a realizar uma tarefa. As aplicações com GUIs são, portanto, baseadas em eventos, que geralmente são gerados pelo usuário. Quando um usuário interage com um componente GUI, ele gera um evento, que resulta numa tarefa a ser executada. Alguns eventos comuns são o clicar em um botão, o digitar numa caixa de texto ou o selecionar uma opção de uma lista. O código que realiza uma tarefa em resposta ao evento é chamado de handler de evento, e o processo total de responder ao evento é conhecido como tratamento do evento.

Page 169: Oswaldo Poo

Tratando eventos de componentes Swing

Vamos conhecer dois componentes do pacote javax.swing que possuem eventos associados: JTextField e JPasswordField.

A classe JTextField estende a classe JTextComponent(javax.swing.text), e possui recursos comuns aos componentes baseados em texto do Swing. Este componente serve, normalmente, para a entrada de dados.

A classe JPasswordField estende JTextField adicionando métodos para o processamento de senhas. Este componente mostra “caracteres eco” à medida que o usuário digita, escondendo os caracteres digitados.

Quando o usuário, após digitar um texto em um dos componentes acima, pressionar “Enter”, será gerado um evento que poderá acionar uma tarefa

Page 170: Oswaldo Poo

Tratando eventos de componentes Swing

Antes que um aplicativo possa responder a um evento, é necessário:– Criar uma classe que represente o handler do evento e instanciar

um objeto dessa classe (o handler do evento).– Implementar uma interface apropriada, conhecida como interface

listener de evento na classe do handler do evento; – Registrar o handler do evento, indicando que o objeto de handler do

evento deve ser notificado quando o evento ocorrer. O componente GUI acionado pelo usuário gera um ActionEvent (pacote java.awt.event), que é processado pelo objeto handler do evento, que implementa uma interface ActionListener (pacote java.awt.event).O aplicativo a seguir utiliza as classes apresentadas para criar e manipular quatro campos de texto. Quando o usuário digita em um dos campos e pressiona “Enter”, o aplicativo exibe um caixa de diálogo com o texto digitado. Observe que o texto só pode ser digitado no componente que estiver sob “foco”. Um componente recebe o “foco”quando o usuário clica sobre ele ou quando “passeia” pelos objetos utilizando a tecla “tab”.

Page 171: Oswaldo Poo

Tratando eventos de componentes Swing

import java.awt.FlowLayout;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;import javax.swing.JFrame;import javax.swing.JTextField;import javax.swing.JPasswordField;import javax.swing.JOptionPane;public class JanelaTexto extends JFrame{

private JTextField campo1; private JTextField campo2;private JTextField campo3; private JPasswordField campo4; public JanelaTexto(){

super("Testa caixas de texto");setLayout(new FlowLayout()); // layout do framecampo1 = new JTextField(10); //caixa com 10 colunas add( campo1 ); // adiciona campo1 à janela

Page 172: Oswaldo Poo

Tratando eventos de componentes Swing

campo2 = new JTextField("Campo editável");add(campo2); campo3 = new JTextField("Não editável", 10);campo3.setEditable(false); // desativa ediçãoadd(campo3); campo4 = new JPasswordField("Senha",10);add(campo4);//instancia o objeto handler do eventoTrataEvento handler = new TrataEvento();campo1.addActionListener(handler);//registra handlercampo2.addActionListener(handler);//registra handlercampo4.addActionListener(handler);//registra handler

} // fim do construtor

Page 173: Oswaldo Poo

Tratando eventos de componentes Swing

// classe que implementa o objeto handler do eventoprivate class TrataEvento implements ActionListener{

public void actionPerformed(ActionEvent evento){String s = ""; if (evento.getSource() == campo1)

s=String.format("Texto 1: %s",campo1.getText()); else if (evento.getSource() == campo2)

s=String.format("Texto 2: %s",campo2.getText());else if (evento.getSource() == campo4)

s = String.format("Texto: %s", new String(campo4.getPassword()));

JOptionPane.showMessageDialog(null, s); }

} // fim da classe TrataEvento} // fim da classe JanelaTexto

Page 174: Oswaldo Poo

Tratando eventos de componentes Swing

A largura em pixels de uma coluna de texto depende o tamanho da fonte atual do campo de texto. Se o texto digitado for mais largo que o campo de 10 colunas do objeto, a parte do texto à direita não ficará visível.

O tratamento de eventos nesse exemplo é realizado por um objeto da classe TrataEvento.

Quando o usuário pressionar “Enter” em um JTextField ou no JPasswordField, o componente gera um ActionEvent (pacote java.awt.event), que é processado por um objeto que implemente a interface ActionListener (pacote java.awt.event).

Para que o evento no objeto GUI seja atendido é necessário registrar previamente o objeto handler no objeto GUI.

Na classe acima, foi utilizado o método actionPerformed de um objeto de tratamento de evento. No caso, a origem dos eventos é o “Enter” nos campos de texto da janela e, quando isto ocorrer, o sistema cria um objeto ActionEvent único que contém informações sobre o evento que acabou de ocorrer, tais como a origem do evento e o texto do campo de texto e passa este objeto em uma chamada para o método actionPerformed do “ouvinte” de eventos, ou listener de eventos.

O método getSource() da classe ActionEvent retorna uma referência àorigem do evento e o método getActionCommand, da mesma classe, retorna o texto do campo de texto.

Page 175: Oswaldo Poo

Tratando eventos de componentes Swing

A seguir temos a classe TestaJanelaTexto que utiliza a classe acima.

import javax.swing.JFrame;public class TestaJanelaTexto {

public static void main( String args[] ) { JanelaTexto jan = new JanelaTexto ();jan.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jan.setSize(250, 120);jan.setVisible(true);

} }

Page 176: Oswaldo Poo

Tipos comuns de eventos

Existem diferentes tipos de eventos em uma interface GUI. Ao ocorrer um evento, as informações sobre o evento são armazenadas em um objeto de uma classe que estende a classe AWTEvent. A hierarquia abaixo contém várias classes de eventos do pacote java.awt.event. Estes tipos de eventos são utilizados tantos em objetos AWT como Swing. Eventos específicos para objetos Swing são declarados no pacote javax.swing.event.

ObjectEventObject

AWTEvent

ActionEventAdjustmentEventItemEventTextEventComponentEvent

ContainerEventFocusEventPaintEventWindowEventInputEvent

KeyEvent

MouseEvent

Page 177: Oswaldo Poo

Tipos comuns de eventos

O modelo de tratamento que vimos aqui é conhecido como modelo de delegação de eventos, pois o processamento de um evento é passado a um objeto particular no aplicativo, o objeto listener ou o ouvinte de eventos.

Para cada tipo de evento, existe uma interface ouvinte de eventos. Um ouvinte de evento é um objeto que implementa uma ou mais interfaces do pacote java.awt.event ou javax.swing.event. Veja algumas interfaces na caixa ao lado

Cada interface ouvinte de eventos especifica os métodos de tratamento de evento que interessem. Quando ocorre um evento, o componente da interface com o qual o usuário interagiu informa seus ouvintes registrados, chamando o método de tratamento de evento adequado de cada ouvinte.

WindowListenerActionListenerAdjustmentListenerComponentListenerContainerListenerFocusListenerItemListenerKeyListenerMouseListenerMouseMotionListenerTextListener

Page 178: Oswaldo Poo

Entendendo o funcionamento de eventos

l Registrando eventos:Cada objeto JComponent, por exemplo JTextField, tem uma variável de instância chamada listenerList que referencia um objeto da classe EventListenerList do pacote javax.swing.event. Podemos entender listenerList como um array . Quando a instrução

campo1.addActionListener (handler)é executada, uma nova entrada que contém uma referência ao objeto TextFieldHandler é colocada na listenerList do JTextField campo1. Ou seja, cada componente GUI mantém sua própria lista de ouvintes que foram registrados para tratar os eventos do componente.

l Chamando o handler de evento:Cada componente GUI suporta vários tipos de eventos: de mouse, de teclado, etc. Quando um evento ocorre, somente os métodos apropriados dos ouvintes de eventos são afetados. Cada tipo de evento tem uma ou mais interfaces ouvintes de eventos correspondentes. ActionEvents são tratados por ActionListeners, MouseEvents são tratados por MouseListeners e MouseMotionListeners, e KeyEvents são tratados por KeyListeners. Quando ocorre um evento, um componente GUI recebe da JVM um ID do evento que especifica o tipo de evento. O componente GUI utiliza o ID para decidir o tipo de ouvinte a ser acionado e o método a ser chamado no objeto ouvinte. Para que isto aconteça, é necessário registrar um handler de evento no componente GUI para o tipo particular de evento que seu aplicativo exige, e o componente GUI fará com que o método apropriado do handler seja chamado.

Page 179: Oswaldo Poo

O componente JButton

Um botão é um componente que o usuário clica com o mouse para disparar uma ação específica. Um aplicativo pode utilizar vários tipos de botões: botões de comando, caixas de seleção e botões de opção.A classe JanelaBotoes cria 2 JButtons com ícones, e realiza o tratamento de eventos dos botões em uma única instância da classe TrataBotao.

import java.awt.FlowLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JFrame;import javax.swing.JButton;import javax.swing.Icon;import javax.swing.ImageIcon;import javax.swing.JOptionPane;public class JanelaBotoes extends JFrame {

private JButton botao1; private JButton botao2; public JanelaBotoes() {

super("Testando Botões");

Page 180: Oswaldo Poo

O componente JButton

setLayout(new FlowLayout());botao1 = new JButton("Botão simples");add(botao1); Icon bug1 = new ImageIcon(

getClass().getResource("bug1.gif"));Icon bug2 = new ImageIcon(

getClass().getResource("bug2.gif"));botao2 = new JButton("Botão com ícone", bug1);botao2.setRolloverIcon(bug2); //icone de rolloveradd(botao2);TrataBotao handler = new TrataBotao();botao2.addActionListener(handler); // registra handlerbotao1.addActionListener(handler); // registra handler

}

Page 181: Oswaldo Poo

O componente JButton

private class TrataBotao implements ActionListener{public void actionPerformed(ActionEvent evento){

JOptionPane.showMessageDialog (JanelaBotoes.this,String.format("Você cliclou no : %s",

evento.getActionCommand()));}

}}

Os components JButtons, assim como os JTextFields, geram ActionsEvents que podem ser processados por qualquer objeto ActionListener. A classe TrataBotaodeclara o método actionPerformed que exibe numa caixa de mensagem o rótulo do botão clicado pelo usuário.

Page 182: Oswaldo Poo

O componente JButton

A classe TestaJanelaBotoes a seguir completa a aplicação.import javax.swing.JFrame;public class TestaJanelaBotoes{

public static void main(String args[]) {JanelaBotoes Jan = new JanelaBotoes(); Jan.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);Jan.setSize( 300, 200 );Jan.setVisible(true);

} }

As caixas de mensagens aparecem centralizadas na janela do aplicativo devido àchamada do método showMessageDialog, utilizar como primeiro argumento JanelaBotoes.this em vez de null. Este primeiro argumento indica o componente que irá conter (container) a caixa de diálogo.

Page 183: Oswaldo Poo

Desafio

1. Usando a interface KeyListener e o evento KeyEvent, implemente um handler para detectar e emitir uma mensagem quando uma tecla for apertada enquanto o foco estiver no componente botao2.

Page 184: Oswaldo Poo

Aula 10 - Objetivo

l Introduzir mais alguns componentes de interfaces gráficas

l Compreender o conceito de exceçãol Aprender a tratar exceções nos programasl Apresentar a cláusula Throws

Page 185: Oswaldo Poo

Recordando...

Na aula passada, vimos como criar uma interface gráfica usando componentes do pacote Swing para entrada de dados (JTextField e JPasswordField) pelo teclado e mouse (JButton). Hoje veremos mais dois componentes (JCheckBox e JRadioButton ). A seguir veremos como tratar os possíveis erros gerados por comandos dentro do próprio programa.

Page 186: Oswaldo Poo

O botão de estado JCheckBox

Os botões de estado JCheckBox e JRadioButton, descendentes do componente JToggleButton, trabalham com as informações de ativado (verdadeiro) ou desativado (falso). Um JRadioButton é diferente de um JCheckBox dado que vários JRadioButton quando agrupados são mutuamente exclusivos, ou seja, somente um dos JRadioButton pode estar selecionado por vez.

A classe a seguir utiliza dois objetos JCheckBox para selecionar o estilo desejado de fonte do texto exibido em um JTextField, um para o estilo negrito, outro para o estilo itálico. Ao iniciar o aplicativo, nenhum dos JCheckBox estará ativado.

Page 187: Oswaldo Poo

O botão de estado JCheckBox

import java.awt.FlowLayout;import java.awt.Font;import java.awt.event.ItemListener;import java.awt.event.ItemEvent;import javax.swing.JFrame;import javax.swing.JTextField;import javax.swing.JCheckBox;public class JanelaComCheckBox extends JFrame{

private JTextField texto; private JCheckBox cb1; private JCheckBox cb2; // construtor adiciona JCheckBoxes e JTextField

public JanelaComCheckBox() {super( "Testa CheckBox" ); // cria JFrame com títulosetLayout( new FlowLayout() ); // define o layout texto = new JTextField("Fonte com novo estilo", 20);texto.setFont(new Font("Serif", Font.PLAIN,14));add(texto); // adiciona textField ao JFrame

Page 188: Oswaldo Poo

O botão de estado JCheckBox

cb1 = new JCheckBox( "Negrito" ); //CheckBox Negritocb2 = new JCheckBox( "Italico" ); //CheckBox Itálicoadd(cb1); //adiciona CheckBox de negrito ao Frameadd(cb2); //adiciona CheckBox de itálico ao FrameCheckBoxHandler h=new CheckBoxHandler();// cria handlercb1.addItemListener(h); //registra o mesmo handler p/..cb2.addItemListener(h); //..os dois controles CheckBox

} // fim do construtor// classe interna para tratar o evento ItemListener

private class CheckBoxHandler implements ItemListener {// controla o estilo de fonte negritoprivate int valNegrito = Font.PLAIN; // controla o estilo de fonte itálicoprivate int valItalic = Font.PLAIN; // responde aos eventos de caixa de seleçãopublic void itemStateChanged(ItemEvent event) {

// processa eventos da caixa de seleção de negrito

Page 189: Oswaldo Poo

O botão de estado JCheckBox

if (event.getSource() == cb1)valNegrito = cb1.isSelected()?Font.BOLD:Font.PLAIN;

// processa eventos da caixa de seleção de itálicoif (event.getSource() == cb2)valItalic = cb2.isSelected()?Font.ITALIC:Font.PLAIN;// configura a fonte do campo de textotexto.setFont(new Font("Serif",

valNegrito + valItalic, 14));} // fim do método itemStateChanged

} // fim da classe CheckBoxHandler} // fim da classe JanelaComCheckBox

Page 190: Oswaldo Poo

O botão de estado JCheckBox

A classe TestaJanelaComCheckBox a seguir é utilizada para testar a classe anterior.import javax.swing.JFrame;public class TestaJanelaComCheckBox{

public static void main( String args[] ) { JanelaComCheckBox janela = new JanelaComCheckBox();janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);janela.setSize(275, 100); //configura tamanho da janelajanela.setVisible(true); // exibe a janela

} // fim do main}

Page 191: Oswaldo Poo

O botão de estado JRadioButton

O botão de opção, instância da classe JRadioButton, é parecido com a caixa de seleção apresentada, pois. também tem dois estados, selecionado (verdadeiro) e não selecionado (falso). A classe a seguir utiliza botões que permitem que apenas um único estilo de fonte seja selecionado por vez.

import java.awt.FlowLayout;import java.awt.Font;import java.awt.event.ItemListener;import java.awt.event.ItemEvent;import javax.swing.JFrame;import javax.swing.JTextField;import javax.swing.JRadioButton;import javax.swing.ButtonGroup;public class JanelaComRadioButton extends JFrame {

private JTextField texto;private Font normalFont; private Font negritoFont; private Font italicoFont; private Font negrItalFont;

Page 192: Oswaldo Poo

O botão de estado JRadioButton

private JRadioButton normalRB; private JRadioButton negritoRB; private JRadioButton italicoRB; private JRadioButton negrItalRB; // buttongroup para armazenar botões de opção

private ButtonGroup grupoRB; // construtor adiciona JRadioButtons ao JFrame

public JanelaComRadioButton() {super("Testa RadioButton" );setLayout(new FlowLayout()); texto = new JTextField("Mudando o estilo", 25 );add(texto); // adiciona textField ao JFrame// cria botões de opçãonormalRB = new JRadioButton("Normal",true); negritoRB = new JRadioButton("Negrito",false); italicoRB = new JRadioButton("Italico",false); negrItalRB = new JRadioButton("Negrito/Itálico",false);add(normalRB); // adiciona o botão do estilo normal

Page 193: Oswaldo Poo

O botão de estado JRadioButton

add(negritoRB); // adiciona o botão de negrito add(italicoRB); // adiciona o botão de itálicoadd(negrItalRB);// adiciona botão de negrito/itálico// cria relacionamento lógico entre JRadioButtons

grupoRB = new ButtonGroup(); // cria ButtonGroupgrupoRB.add(normalRB); // adiciona botão ao grupo grupoRB.add(negritoRB); // adiciona botão ao grupo grupoRB.add(italicoRB); // adiciona botão ao grupo grupoRB.add(negrItalRB); // adiciona botão ao grupo // cria objetos fonte

normalFont = new Font( "Serif", Font.PLAIN, 14 );negritoFont = new Font( "Serif", Font.BOLD, 14 );italicoFont = new Font( "Serif", Font.ITALIC, 14 );negrItalFont = new Font( "Serif", Font.BOLD +

Font.ITALIC, 14 );texto.setFont(normalFont); // configura fonte inicial

Page 194: Oswaldo Poo

O botão de estado JRadioButton

// registra eventos para JradioButtonsnormalRB.addItemListener(

new RadioButtonHandler(normalFont));negritoRB.addItemListener(

new RadioButtonHandler(negritoFont)); italicoRB.addItemListener(

new RadioButtonHandler(italicoFont));negrItalRB.addItemListener(

new RadioButtonHandler(negrItalFont));}// fim do construtor RadioButtonFrame// classe interna para tratar eventos de botão de opção

private class RadioButtonHandler implements ItemListener{private Font font; // fonte associada com o listenerpublic RadioButtonHandler(Font f) {

font = f; // configura a fonte desse listener} // fim do construtor RadioButtonHandler

Page 195: Oswaldo Poo

O botão de estado JRadioButton

// método de tratamento dos eventos de botão de opçãopublic void itemStateChanged(ItemEvent event) {

texto.setFont(font); // configura fonte de texto} // fim do método itemStateChanged

} // fim da classe RadioButtonHandler interna e private}

A classe TestaJanelaComRadioButton, a seguir, testa a classe anterior.import javax.swing.JFrame;public class TestaJanelaComRadioButton{

public static void main( String args[] ){JanelaComRadioButton jan = new JanelaComRadioButton();

jan.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jan.setSize(300, 100); // define tamanho da janelajan.setVisible(true); // exibe a janela

} // fim de main}

Page 196: Oswaldo Poo

Ocorrência de exceções

Uma exceção é uma indicação de um problema que ocorre durante a execução de um programa. O tratamento da exceção permite que programadores gerem aplicativos que possam resolver situações em que exceções acorram, objetivando a continuidade na execução, garantindo aos aplicativos características de robustez e tolerância a falhas.

Vejamos o que ocorre em um aplicativo que não utiliza tratamento de erro. A classe a seguir solicita do usuário dois inteiros e calcula seu quociente. Neste caso, podemos verificar que as exceções são lançadas (ocorrem) quando um problema é detectado e não há como tratá-lo.

import java.util.Scanner;public class GeraErro{// demonstra exceção de div. por zero

public static int dividir(int numerador,int denominador){return numerador / denominador; // possivel erro

}

Page 197: Oswaldo Poo

Ocorrência de exceções

public static void main(String args[]){Scanner scanner = new Scanner( System.in );System.out.print( "Entre com numerador inteiro: " );int numerador = scanner.nextInt();System.out.print( "Entre com denominador inteiro: " );int denominador = scanner.nextInt();int resultado = dividir (numerador, denominador);System.out.printf("\n %d / %d = %d\n",

numerador, denominador, resultado);} // fim do main

}Se executarmos o aplicativo anterior e digitarmos dois números inteiros, sendo o

segundo diferente de zero, o aplicativo executará normalmente informando o inteiro resultando da divisão dos dois números.

Se em uma execução digitarmos para denominador o valor zero, ocorre erro e várias linhas, conhecidas como rastreamento de pilha, são apresentadas. Neste caso, como não épossível dividir por zero, a exceção ArithmeticException do pacote java.lang é lançada e uma informação extra “/ by zero” fornece detalhes sobre a exceção específica.

Se, em outra execução, digitarmos um caractere não numérico, é gerada uma ocorrência de InputMismatchException do pacote java.util.

Note que nas linhas rastreamento de pilha, há informação da linha de código em que a exceção é detectada.

Page 198: Oswaldo Poo

Tratamento das exceções

Reescrevemos o aplicativo anterior utilizando tratamento de exceções para processar as ArithmeticExceptions e InputMismatchExceptions. A classe agora trata as exceções de forma que, se o usuário cometer um erro, o programa captura e trata as exceções, permitindo a re-inserção dos dados.

import java.util.InputMismatchException;import java.util.Scanner;public class TrataErro{

// demonstra o lançamento de exceções public static int dividir(int numerador,

int denominador) throws ArithmeticException{return numerador / denominador; //possivel erro

} // fim de método quotientepublic static void main( String args[] ) {

Scanner ent = new Scanner(System.in); // determina se mais entradas são necessarias

boolean continueLoop = true;

Page 199: Oswaldo Poo

Tratamento das exceções

do { try {

System.out.print("Entre c/ numerador: " );int numerador = ent.nextInt();

System.out.print("Entre c/ denominador: ");int denominador = ent.nextInt();int resultado = dividir(numerador, denominador);System.out.printf("\n%d / %d = %d\n", numerador,

denominador, resultado ); continueLoop = false; // entrada ok; fim de loop

} // fim de trycatch(InputMismatchException inputMismatchException){

System.err.printf( "\nExceção : %s\n",inputMismatchException );

// descarta entrada para nova tentativaent.nextLine();

System.out.println("Entre com inteiros.\n");} // fim de catch

Page 200: Oswaldo Poo

Tratamento das exceções

catch (ArithmeticException arithmeticException){System.err.printf("\nExceção: %s\n",

arithmeticException);System.out.println("Divisão por zero.” +

"Tente novamente.\n" ); } // fim de catch

} while (continueLoop); // fim de do/while} // fim do main

}

Page 201: Oswaldo Poo

Tratamento das exceções

A classe acima contém um bloco try que inclui o código que pode “lançar” uma exceção, deixando claro que ao ocorrer uma exceção, o restante do código a partir na instrução que ocasionou a exceção não é executado.

A instrução try consiste na palavra chave try seguida por um bloco de código entre chaves “{}”, e normalmente nos referirmos como bloco try ao(s) comando(s) dentro da chaves da instrução try.

O bloco try é seguido por dois blocos catch, um que trata uma InputMismatchException e outro que trata uma ArithmeticException. Um bloco catch, também chamado de cláusula catch ou handler de exceção, captura e trata a exceção. Um bloco catch inicia-se com a palavra-chave catch e é seguido por um parâmetro entre parênteses (parâmetro de exceção) e um bloco de código entre chaves. Da mesma forma, é comum utilizarmos o termo bloco catch para designar o código entre as chaves. Pelo menos um bloco catch ou um bloco finally deve se seguir imediatamente ao bloco try.

Todo bloco catch especifica um parâmetro de exceção entre parênteses que identifica o tipo de exceção que o handler pode processar. Quando uma exceção ocorre em um bloco try, o bloco catch que é executado é aquele que corresponde exatamente ao tipo da exceção que ocorreu ou a uma superclasse dela. O nome do parâmetro deexceção permite ao bloco catch utilizar o objeto de exceção, como por exemplo, chamar implicitamente o método toString da exceção capturada para exibir informações básicas sobre a exceção. Os programadores Java costumam utilizar simplesmente a letra ecomo o nome de parâmetros de exceção.

Page 202: Oswaldo Poo

Utilizando a cláusula throws

Na aplicação anterior, especificamente na declaração do método dividirutiliza-se a cláusula throws. Esta declaração especifica que o método pode lançar uma exceção em caso de erro. A referida cláusula, sintaticamente, pode aparecer após a lista de parâmetros do método e conter uma lista de exceções separadas por vírgulas que o método lançará se ocorrer um problema. Essas exceções podem ser lançadas por instruções no corpo de método ou por métodos chamados no corpo. Um método pode lançar exceções das classes listadas em sua cláusula throws ou de suas subclasses. No caso da classe TrataErro, os clientes do método dividir() são informados que o método pode lançar uma ArithmeticException.

Todas as classes de exceção do Java herdam, direta ou indiretamente, da classe Exception, formando uma hierarquia de herança que pode ser estendida pelos programadores para formar sua própria classe de exceção.

Page 203: Oswaldo Poo

Utilizando a cláusula throws

Page 204: Oswaldo Poo

Utilizando a cláusula throws

Várias classes de exceção podem ser derivadas de uma superclasse comum. Se um handler catch for escrito para capturar objetos de exceção de um tipo de superclasse, ele também pode capturar todos os objetos de subclasses dessa classe. Se houver múltiplos blocos catch que correspondem a um tipo particular de exceção, somente o primeiro bloco catchcorrespondente executará na ocorrência da exceção desse tipo. Se seguirmos a um bloco try, com um bloco catch para o tipo AtithmeticException e outro catch para o tipo Exception, somente o primeiro bloco correspondente executaria.

Page 205: Oswaldo Poo

O Bloco Finally

Os programas que obtêm certos recursos do ambiente operacional devem retorna-lospara evitar os supostos vazamentos de recursos. O tipo mais comum é o vazamento de memória. O Java realiza a coleta automática de lixo de memória não mais utilizada por programas, evitando assim a maioria dos vazamentos de memória. Entretanto outros tipos de vazamentos podem ocorrer, como por exemplo, arquivos, conexões com bancos de dados, com redes que não são fechadas adequadamente e que talvez não fiquem disponíveis para uso em outros aplicativos.

O bloco finally, que também é composto de chaves, é opcional. Se estiver presente, este bloco é colocado depois do último bloco catch como mostrado a seguir. O Java garante que o bloco finally caso esteja presente, executará se uma exceção for lançada no bloco trycorrespondente ou quaisquer de seus blocos catch. Também executará se um bloco try fechar utilizando a instrução return, break ou continue. Entretanto não executará se o aplicativo fechar antes de um bloco try chamando o método System.exit que encerra imediatamente o aplicativo.

try{}catch (TipoExceção1 exceção1){}catch (TipoExceção2 exceção2){}finally{<< instruções de liberação de recursos >>}

Page 206: Oswaldo Poo

Tratamentos aninhados

Se uma exceção que ocorre em um bloco try não puder ser capturada por handlers catch desse bloco try, o aplicativo pula o restante do bloco try e prossegue para o bloco finally. Então o programa passa a exceção para o próximo bloco try externo caso haja, normalmente no método chamador, onde um bloco catch pode capturá-la.

A classe a seguir mostra que o bloco finally ainda executará mesmo que não seja lançada uma exceção no bloco try correspondente.

public class UsandoExceptions {public static void main( String args[] ) {

try {lancaExcecao(); // chama método throwException

} // exceção lançada por throwExceptioncatch ( Exception e ) {

System.err.println( "Exceção tratada no main" );System.out.printf( "Exceção : %s\n", e );

} naolancaExcecao();

} // fim de main

Page 207: Oswaldo Poo

Tratamentos aninhados

// demonstra try...catch...finallypublic static void lancaExcecao() throws Exception{

try { // lança uma exceção System.out.println( "Método lancaExcecao" );throw new Exception(); // gera a exceção

} // captura exceção lançada em trycatch ( Exception e ) {

System.err.println("Exceção tratada no método lancaExcecao" );

System.out.printf( "Exceção : %s\n", e );throw e; // Atenção: Lança novamente para

// processamento adicional no main// qualquer código aqui não seria alcançado

} // fim de catch

Page 208: Oswaldo Poo

Tratamentos aninhados

finally { // executa independentemente do que // ocorre em try...catch

System.err.println("Finally executado em lancaExcecao" );

} // fim de finally// qualquer código aqui não seria atingido, // exceção lançada de novo em catch

} // demonstra finally quando nenhuma exceção ocorrerpublic static void naolancaExcecao() {

try { // bloco try não lança uma exceçãoSystem.out.println( "Método naolancaExcecao" );

} // fim de trycatch ( Exception e ) { // não executa

System.err.println( e );} // fim de catch

Page 209: Oswaldo Poo

Tratamentos aninhados

finally { // executa independentemente do que ocorre // em try...catch

System.err.println( "Finally executado em naolancaExcecao" );

} // fim de finallySystem.out.println( "Fim de naolancaExcecao" );

} }

Page 210: Oswaldo Poo

Tratamentos aninhados

A instrução no método throwException()throw new Exception();

é conhecida como instrução throw e é executada para informar a ocorrência de uma exceção – dizemos que o método relança a exceção. Os programadores podem relançar exceções utilizando essa instrução indicando a um método cliente que ocorreu um erro.A instrução no método lancaExcecao()

throw e;relança a exceção. Exceções são relançadas quando um bloco catch não pode processar uma exceção, ou só pode parcialmente. Relançar uma exceção adia o tratamento de exceção para outro bloco catch associado com uma instrução tryexterna. Uma exceção é relançada utilizando a palavra-chave throw, seguida por uma referência ao objeto de exceção que acabou de ser capturado. Um exceção não pode ser relançada de um bloco finally. No método notthrowException() nenhuma exceção é lançada no bloco try, então o programa “pula” o bloco catch. Apesar disto, o bloco finally é executado.

Page 211: Oswaldo Poo

Desafio

1. Analise o código a seguir:import javax.swing.*;import java.awt.*;public class TelaMensagem extends JFrame {

private JButton btnExibir;private JTextField txtExibir;public TelaMensagem() {

txtExibir = new JTextField();btnExibir = new JButton();getContentPane().setLayout( new FlowLayout());setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);setResizable(false);txtExibir.setColumns(40);getContentPane().add(txtExibir);btnExibir.setText("Exibir");getContentPane().add(btnExibir);pack();

}public static void main( String[] args ){

new TelaMensagem().setVisible(true);}

Utilizando a linguagem Java escreva o código que adicione um evento para o botão responsável por exibir na tela o valor digitado na caixa de texto. Este valor deve ser um número positivo. Se esta condição não for atendida, o sistema deve capturar e tratar a exceção.

Page 212: Oswaldo Poo

Aula 11 - Objetivos

l Introduzir mais alguns gerenciadores de layoutl Compreender o FlowLayout, BorderLayout,

GridLayoutl Apresentar layouts mais complexosl Revisar os conceitos aprendidos em um

estudo de caso

Page 213: Oswaldo Poo

Recordando...

Na aula passada, vimos como tratar os possíveis erros gerados por comandos dentro do próprio programa. Continuamos, entretanto, a trabalhar com aplicações gráficas que usavam o mesmo tipo de layout (FlowLayout). Hoje veremos outros tipos de layout e treinaremos com o estudo de caso de uma aplicação completa para consolidar o aprendido.

Page 214: Oswaldo Poo

Gerenciadores de layout

Para que possamos organizar a arrumação dos componentes GUI em um container, existem os de gerenciadores de layout. Em um layout básico, como o que vimos até agora, em vez de determinar a posição e o tamanho exatos de cada componente GUI na janela, o programador apenas define a aparência e o comportamento básicos, deixando o gerenciador de layout encarregado dos detalhes de arrumação.

Todos os gerenciadores implementam a interface LayoutManager do pacote java.awt. O método setLayout da classe Container recebe como argumento um objeto que implementa a interface LayoutManager.

Page 215: Oswaldo Poo

Gerenciadores de layout

Há três maneiras de organizar componentes em uma GUI:

1. Posicionamento absoluto – configurando o layout do containercomo null, é possível especificar o tamanho de cada componente e sua posição absoluta em relação ao canto superior esquerdo do container.

2. Gerenciadores de layout – Com eles é mais simples e mais rápido criar uma GUI, mas normalmente se perde algum controle sobre o tamanho e posicionamento de controles GUI;

3. Programação visual em um IDE – Estes ambientes facilitam a criação de GUIs. Em geral, todo IDE visual fornece uma ferramenta de desenho GUI que permite arrastar e soltar componentes GUI de uma caixa de ferramentas em uma área de desenho (janela). O IDE gera o código que cria a GUI e, além disso, é possível adicionar os códigos de tratamento de eventos para os componentes.

Page 216: Oswaldo Poo

BorderLayout

Este gerenciador, que é o padrão no JFrame, organiza componentes em cinco regiões: NORTH, SOUTH, EAST, WEST e CENTER. A classe BorderLayout estende a classe Object e implementa a interface LayoutManager2, subinterface de LayoutManager que adiciona vários métodos para obter um processamento de layout mais aprimorado.

Este gerenciador limita um Container a conter no máximo cinco componentes, um em cada região, porém o componente da região pode ser um outro container, no qual outros componentes podem ser anexados.

Page 217: Oswaldo Poo

BorderLayout

A classe a seguir usa o BorderLayout. Os argumentos do construtor especificam o número de pixels dos espaços horizontal e vertical entre os componentes. Nela é utilizada uma outra versão do construtor add da classe Container que aceita dois argumentos: o componente a adicionar e a região em que o componente deve aparecer.

import java.awt.BorderLayout;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;import javax.swing.JFrame;import javax.swing.JButton;public class JanelaComBorderLayout

extends JFrame implements ActionListener { private JButton botoes[];// array de botõesprivate final String nomes[] = {"Esconde Norte",

"Esconde Sul", "Esconde Leste","Esconde Oeste", "Esconde Centro"};

private BorderLayout meuLayout; // objeto borderlayoutpublic JanelaComBorderLayout() { // configura a GUI

Page 218: Oswaldo Poo

BorderLayout

super( "Demonstração do BorderLayout" );// espaços de 5 pixels na vertical e na horizontalmeuLayout = new BorderLayout( 5, 5); setLayout(meuLayout); // configura o layout do framebotoes = new JButton[nomes.length];// instancia array // cria botoes e registra ouvintes para elesfor ( int cont = 0; cont < nomes.length; cont++ ){

botoes[cont] = new JButton(nomes[cont]);// cria botãobotoes[cont].addActionListener(this);// registra

} // final do foradd(botoes[0], BorderLayout.NORTH); add(botoes[1], BorderLayout.SOUTH);add(botoes[2], BorderLayout.EAST);add(botoes[3], BorderLayout.WEST);add(botoes[4], BorderLayout.CENTER);

} // fim do construtor BorderLayoutFrame

Page 219: Oswaldo Poo

BorderLayout

// trata os eventos de botãopublic void actionPerformed(ActionEvent esteEvento){

// verifica a origem de evento e o painel de layoutfor (JButton botao : botoes) {

if (esteEvento.getSource() == botao)botao.setVisible(false); //oculta botão clicado

elsebotao.setVisible(true); // e mostra os demais

} meuLayout.layoutContainer(getContentPane());//re-layout

} // fim do método actionPerformed}

Page 220: Oswaldo Poo

BorderLayout

A classe a seguir é utilizada para testar a classe JanelaComBorderLayout.

import javax.swing.JFrame;public class TestaJanelaComBorderLayout{

public static void main( String args[] ) { JanelaComBorderLayout jan = new JanelaComBorderLayout(); jan.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jan.setSize( 400, 200 ); // tamanho da janelajan.setVisible(true); // exibe janela

}}

Page 221: Oswaldo Poo

BorderLayout

A classe acima implementa a interface ActionListener diretamente, daíJanelaComBorderLayout tratará os eventos de JButtons. A linha

buttons[cont].addActionListener(this);passa a referência this para o método addActionListener de cada JButton.

Quando o usuário clica em um JButton particular no layout, o método ActionPerformed é executado. A instrução for utiliza um desvio condicional composto para ocultar o JButton particular que gerou o evento. A linha

layout.layoutContainer( getContentPane() );utiliza o método layoutContainer para recalcular o layout do painel de conteúdo. As regiões no BorderLayour alteram a forma quando JButtons são ocultados e exibidos em outras regiões da seguinte forma: se todas as regiões são ocupadas, o espaço do container inteiro é coberto por componentes GUI; se a região NORTH ou SOUTH não for ocupada, os componentes das regiões WEST, CENTER e EAST expandem-se verticalmente para ocupar o espaço livre; se a região CENTER não for ocupada, a área é deixada vazia – os outros componentes não se expandem para o espaço deixado por esta região.

Page 222: Oswaldo Poo

GridLayout

O GridLayout divide o container em uma grade de modo que os componentes podem ser colocados nas linhas e colunas. A classe GridLayout herda diretamente da classe Object, além de implementar LayoutManager. Cada componente em um GridLayout tem a mesma largura e altura. Componentes GUIs são adicionados a partir da célula na parte superior esquerda da grade e continuando da esquerda para a direita até a linha estar cheia. O processo continua na linha abaixo.

Page 223: Oswaldo Poo

GridLayout

A classe JanelaComGridLayout a seguir utiliza seis JButtons.import java.awt.GridLayout;import java.awt.Container;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;import javax.swing.JFrame;import javax.swing.JButton;public class JanelaComGridLayout extends JFrame

implements ActionListener {private JButton botoes[]; private final String nomes[] = { "Um", "Dois", "Três",

"Quatro", "Cinco", "Seis" };private boolean muda = true; // alterna entre layoutsprivate Container container; // painel de conteúdoprivate GridLayout grid1; // primeiro gridlayoutprivate GridLayout grid2; // segundo gridlayoutpublic JanelaComGridLayout(){// construtor sem argumento

Page 224: Oswaldo Poo

GridLayout

super( "Demostração do GridLayout" );grid1 = new GridLayout(2, 3, 5, 5); //grid 2x3 espaço 5grid2 = new GridLayout(3, 2);//grid 3x2 sem espaçocontainer = getContentPane(); //painel de conteúdosetLayout( grid1 ); // configura o layoutbotoes = new JButton[nomes.length]; // cria array for (int cont = 0; cont < nomes.length; cont++){

botoes[cont] = new JButton(nomes[cont]);botoes[cont].addActionListener(this);// adiciona o botão ao JFrameadd(botoes[cont] );

} // for final} // fim do construtor // trata eventos de botão alternando entre layouts

Page 225: Oswaldo Poo

GridLayout

public void actionPerformed( ActionEvent evento ){if (muda) // configura layout como Segundo

container.setLayout(grid2); else // configura layout como primeiro

container.setLayout(grid1); muda = !muda; // alterna para valor opostocontainer.validate(); // refaz o layout do container

} // fim do método actionPerformed}

Page 226: Oswaldo Poo

GridLayout

A classe TestaJanelaComGridLayout, a seguir, testa a classe acima.import javax.swing.JFrame;public class TestaJanelaComGridLayout {public static void main( String args[] ) { JanelaComGridLayout janela = new JanelaComGridLayout();janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);janela.setSize( 400, 200 ); // configura a janelajanela.setVisible(true); // exibe a janela

} // fim de main}

As linhasgrid1 = new GridLayout( 2, 3, 5, 5 ); grid2 = new GridLayout( 3, 2 );

criam duas instâncias de GridLayout. O primeiro construtor especifica um GridLayout com 2 linhas, 3 colunas e 5 pixels tanto para espaçamento vertical com para o horizontal. O segundo objeto GridLayout especifica um gerenciador com 3 linhas, 2 colunas e espaçamentos-padrão de 1 pixel.A linha

container.validate();reformata, de outra maneira, um container cujo layout foi alterado. O método validate() recalcula o layout do container com base no gerenciador atual para o container e o conjunto atual de componentes GUIs exibidos.

Page 227: Oswaldo Poo

Layouts mais complexos

Interfaces mais complexas exigem que cada componente seja colocado na posição exata. Normalmente se constituem de múltiplos painéis, com componentes de cada painel organizados em um layout específico. A classe JPanel estende JComponent , que por sua vez estende a classe JContainer, de modo que JPanel é um container. Portanto, cada JPanel pode ter componentes, inclusive outros painéis, anexados a ele com o método add().

Page 228: Oswaldo Poo

Layouts mais complexos

O aplicativo a seguir mostra um layout mais complexo com vários JButtonscolocados na região South de um BorderLayout.

import java.awt.GridLayout;import java.awt.BorderLayout;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.JButton;public class JanelaComPainel extends JFrame {

private JPanel painelBotoes; //painel p/ armazenar botõesprivate JButton botoes[]; // array de botõespublic JanelaComPainel(){// construtor sem argumento

super( "Demonstração de Panel" );botoes = new JButton[5]; // cria array de botõespainelBotoes = new JPanel(); // configura painelpainelBotoes.setLayout( new GridLayout(

1, botoes.length ) );

Page 229: Oswaldo Poo

Layouts mais complexos

// cria e adiciona botões ao painelfor ( int cont = 0; cont < botoes.length; cont++ ) {

botoes[cont] = new JButton("Botão " + (cont + 1));painelBotoes.add(botoes[cont]); //adiciona botão

} // final do foradd(painelBotoes, BorderLayout.SOUTH);//adiciona painel

} // fim do construtor }

A classe a seguir testa a classe JanelaComPainel apresentada.import javax.swing.JFrame;public class TestaJanelaComPainel extends JFrame {

public static void main(String args[]){ JanelaComPainel janela = new JanelaComPainel(); janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);janela.setSize(450, 200); janela.setVisible(true);

} }

Page 230: Oswaldo Poo

Layouts mais complexos

Depois do objeto painelBotoes ser declarado e instanciado, a instrução

painelBotoes.setLayout(new GridLayout(1,botoes.length));

configura o layout como um GridLayout de 1 linha e 5 colunas. Já a linha:

painelBotoes.add(botoes[cont]);

adiciona os botões diretamente ao JPanel, dado que JPanel não tem painel de conteúdo conforme um JFrame. Logo após, é utilizado o padrão defaultBorderLayout para adicionar buttonJPanel à região South. A região South ficarátão grande quanto os botões no buttonJPanel. Um JPanel é dimensionado aos componentes que ele contém. À medida que mais componentes são adicionados, o JPanel cresce.

Page 231: Oswaldo Poo

Desafio

1. Uma empresa solicita o desenvolvimento de um software que jogue xadrez sozinho contra humanos. Para isso é preciso ter a informação de como se move cada peça dentro do jogo, e seu respectivo grau de importância. O rei, por exemplo, só se move uma casa em qualquer direção e é a peça mais importante, ao passo que a rainha se move o quanto quiser em qualquer direção e é a segunda peça mais importante. A princípio, dada uma posição X, Y toda peça pode se mover para lá. Se necessário, cada peça específica define sua maneira de se mover e sua hierarquia no jogo.Atenção deve ser dada aos conceitos de orientação a objeto como herança e encapsulamento. Informe a nova posição de uma peça, após cada movimento dela.

l Com base no diagrama UML a seguir, utilizando a linguagem Java, implemente todas as classes dos diagramas abaixo, encapsulando obrigatoriamente todos os atributos.

l Implemente o método mover() para movimentar o Rei, gerando uma exceção quando houver tentativa de movimentar o Rei com distância maior que uma casa.

Page 232: Oswaldo Poo

Desafio

Page 233: Oswaldo Poo

Desafio

2. Utilizando a linguagem Java escreva o código que adicionaria um evento para o botão responsável por exibir na tela o valor digitado na caixa de texto. Este valor deve ser um número positivo. Se esta condição não for atendida, o sistema deve levantar uma exceção.

import javax.swing.*;import java.awt.*;import java.awt.event.*;public class TelaMensagem extends JFrame {

private JButton btnExibir;private JTextField txtExibir;public TelaMensagem() {

txtExibir = new JTextField(); btnExibir = new JButton();getContentPane().setLayout(new FlowLayout());setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);setResizable(false); txtExibir.setColumns(40); getContentPane().add(txtExibir);btnExibir.setText("Exibir"); getContentPane().add(btnExibir);pack();

}public static void main( String[] args ){

new TelaMensagem().setVisible(true);}

Page 234: Oswaldo Poo

Desafio

3. Crie um programa em Java para manipular a classe Rainha criada na questão número 1. Este programa recebe como parâmetro de linha de comando a posição inicial da peça.e deve movê-la para a posição 2, 4. Antes e depois de mover a peça, escreva na tela para onde ela está.

Orientações:– Pode-se partir do princípio que o usuário sempre informará os dados

necessários na linha de comando;– Utilize os métodos de manipulação do objeto para escrever e ler suas

propriedades, inclusive na hora de escrevê-las na tela.

Page 235: Oswaldo Poo

Aula 12 - Objetivos

l Revisar os conceitos aprendidos em um estudo de caso

Page 236: Oswaldo Poo

Recordando...

Na aula passada, vimos outros tipos de layout e treinamos com o estudo de caso de uma aplicação completa para consolidar o aprendido.

Hoje veremos outro estudo de caso. Éimportante que você faça o estudo de hoje, procurando consultar as aulas passadas para identificar onde se encontra a teoria associada e qual a sintaxe dos comandos. Mãos à obra!

Page 237: Oswaldo Poo

Estudo de caso

1. Uma academia de ginástica possui um programa para calcular a quantidade máxima de batimentos cardíacos a que cada atleta deve ser submetido durante os exercícios.

Cada pessoa possui uma matrícula e são mantidas informações sobre o peso, a idade de cada atleta, fatores que são levados emconsideração para o cálculo dos batimentos cardíacos máximos. O diagrama abaixo mostra uma parte das classes existentes. O batimento cardíaco máximo dos homens deve ser equivalente a um valor base –(peso + idade). O batimento cardíaco máximo das mulheres deve ser equivalente ao valor base – (peso + idade), caso tenham até 60 anos. Para mulheres a partir de 61 anos os anos excedentes a 60 devem ser descontados em dobro do valor base. Os homens, quando estiverem se preparando para alguma competição, podem ter seu batimento básico acrescido de um valor que varia de indivíduo para indivíduo.

Page 238: Oswaldo Poo

Estudo de caso

Page 239: Oswaldo Poo

Estudo de caso

o valor do possível incremento a ser somado ao batimento máximo (no caso de homem em preparação para competição) e escrever no console de saída a matrícula da pessoa armazenada e a batimento cardíaco máximo calculado. Nesta questão é obrigatória a chamada dos métodos polimórficos de cálculo do batimento máximo, bem como dos métodos de manipulação dos atributos.

Page 240: Oswaldo Poo

Estudo de caso

2. Analise o código Java abaixo:import javax.swing.*;import java.awt.*;public class TelaTeste extends JFrame {

private JLabel rotulo;private JButton botao;private JTextField texto;public TelaTeste () {

super("Tela de teste");setLayout(new FlowLayout());rotulo = new JLabel("Digite a idade do atleta:" );texto = new JTextField(10);botao = new JButton("Conferir");add(rotulo); add(texto);add(botao);pack();

}

Page 241: Oswaldo Poo

Estudo de caso

public static void main( String[] args ){TelaTeste tela = new TelaTeste();t.setVisible(true);t.setDefaultCloseOperation(EXIT_ON_CLOSE);

}}

Escreva em Java o código para registrar e tratar o evento de click no botão. A rotina de tratamento deve ler um valor inteiro de uma caixa de texto e exibir uma janela com a mensagem “Criança”, caso a idade seja até 11 anos, “Adolescente”, caso a idade seja entre 12 e 17 anos e “Adulto” caso a idade seja maior ou igual a 18 anos. Caso o valor digitado seja negativo deve ser exibida uma janela com a mensagem “Idade deve ser positiva.”. Caso, ainda, o texto não seja um inteiro válido, o sistema deve tratar a exceção e exibir uma janela com a mensagem “Valor digitado não é um número inteiro.”