Baixe o app para aproveitar ainda mais
Prévia do material em texto
Técnicas de Programação Conteúdo Prático Prof. Dr. Iális Cavalcante Gonçalo Melo Rosemberg M. de Oliveira 11 de março de 2014 Apostila Complementar 1 Para o desenvolvimento de uma aplicação em Java podemos encontrar di- versas maneiras de resolver um problema. Para a simples verificação de um número inteiro a fim de enquadrar este no grupo de números primos ou per- feitos permite-se diferentes formas de codificação de sua solução. Vejamos a seguir, algumas destas possibilidades. Observe o código-fonte do arquivo Numeros01.java. 1 2 package aula; 3 4 import java.io.BufferedReader; 5 import java.io.InputStreamReader; 6 7 public class Numeros01{ 8 9 /* método principal */ 10 public static void main(String args []){ 11 BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in)); 12 try{ 13 // leitura do número inteiro 14 int num = Integer.parseInt(entrada.readLine () ); 15 16 // verificação 01 - se o número é primo ou nã o 17 18 int cont = 0; // contador do número de divisores do valor lido 19 for(int i = 1; i <= num; i++){ 1 2 20 // se o resto desta divisão inteiro é zero , então encontrou -se um divisor 21 if(num%i == 0) 22 cont ++; 23 } 24 // se encontrou apenas dois divisores para o valor lido , então o mesmo é primo 25 if(cont == 2) 26 System.out.println(num+" é um número primo!"); 27 else 28 System.out.println("O número "+num+" não é primo!"); 29 // fim da verificação 01 30 31 // verificação 02 - se o número é perfeito ou não 32 33 int soma = 0; // acumulador dos divisores do valor lido 34 for(int i = 1; i < num; i++){ 35 // se o resto desta divisão inteiro é zero , então encontrou -se um divisor 36 if(num%i == 0) 37 soma += i; 38 } 39 // se a soma dos divisores é igual ao valor lido , então o mesmo é um número perfeito 40 if(soma == num) 41 System.out.println(num+" é um número perfeito!"); 42 else 43 System.out.println("O número "+num+" não é perfeito!"); 44 // fim da verificação 02 45 }catch(Exception erro){ 46 System.out.println("Erro de leitura!"); 47 } 48 } 49 3 50 } Código 1: Numeros01.java Vale ressaltar que a classe deve ter o mesmo nome do arquivo. Não respeitar essa construção do seu código gera um erro de compilação. Uma forma de modularizar o programa presente em Numeros01.java é fazer uso de duas funções (que assim como os procedimentos, em Java são nomeados de métodos) para destacar os testes para verificação da condição de um número primo e/ou perfeito. No código-fonte de Numeros02.java temos isso expresso pelos métodos isPrimo e isPerfeito. 1 package aula; 2 3 import java.io.*; 4 5 public class Numeros02{ 6 7 /* método principal */ 8 public static void main(String args []){ 9 BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in)); 10 try{ 11 // leitura do número inteiro 12 int num = Integer.parseInt(entrada.readLine () ); 13 14 // verificação 01 - se o número é primo ou nã o 15 16 boolean testePrimo = isPrimo(num); 17 // se encontrou apenas dois divisores para o valor lido , então o mesmo é primo 18 if(testePrimo) 19 System.out.println(num+" é um número primo!"); 20 else 21 System.out.println("O número "+num+" não é primo!"); 22 // fim da verificação 01 23 4 24 // verificação 02 - se o número é perfeito ou não 25 26 boolean testePerfeito = isPerfeito(num); 27 // se a soma dos divisores é igual ao valor lido , então o mesmo é um número perfeito 28 if(testePerfeito) 29 System.out.println(num+" é um número perfeito!"); 30 else 31 System.out.println("O número "+num+" não é perfeito!"); 32 // fim da verificação 02 33 }catch(Exception erro){ 34 System.out.println("Erro de leitura!"); 35 } 36 } 37 38 /** 39 * Método para verificação se um número é primo ou nã o 40 * @param numero valor de entrada 41 * @return verdadeiro se número é primo , falso em caso contrário 42 */ 43 static boolean isPrimo(int numero){ 44 int cont = 0; // contador do número de divisores do valor lido 45 for(int i = 1; i <= numero; i++){ 46 // se o resto desta divisão inteiro é zero , então encontrou -se um divisor 47 if(numero%i == 0) 48 cont ++; 49 } 50 if(cont == 2) return true; 51 else return false; 52 } 53 54 /** 55 * Método para verificação se um número é perfeito ou 5 não 56 * @param numero valor de entrada 57 * @return verdadeiro se número é perfeito , falso em caso contrário 58 */ 59 static boolean isPerfeito(int numero){ 60 int soma = 0; // acumulador dos divisores do valor lido 61 for(int i = 1; i < numero; i++){ 62 // se o resto desta divisão inteiro é zero , então encontrou -se um divisor 63 if(numero%i == 0) 64 soma += i; 65 } 66 if(soma == numero) return true; 67 else return false; 68 } 69 } Código 2: Numeros02.java Segue-se como padrão em Java a prática de nomear os métodos que re- tornam um valor do tipo booleano com a palavra is seguida do objetivo do método. Por exemplo: se um método busca identificar se um número é par, então este mesmo será identificado por isPar (mais correto ainda seria nomear como isEven correspondendo a pergunta “É par?” em inglês, mas adaptamos à nossa língua nativa na medida do possível). Destaca-se ainda a importação de classes externas através da palavra- chave import. Em Numeros01.java temos a importação específica das clas- ses java.io.BufferedReader e java.io.InputStreamReader. Essa importação é ocultada pelo comando import java.io.*; no Numeros02.java. Neste caso, a presença do * (asterisco) realiza a importação de todas as classes presentes no pacote java.io. Sendo assim, além das classes BufferedReader e InputStream- Reader, todas as demais classes deste mesmo pacote também são importadas no segundo código-fonte. E por falar em pacotes... Observe que nestes mesmos programas citados anteriormente, temos a presença do comando package aula;. Este último indica que os dois arquivos (e como será visto posteriormente, todos os arquivos deste tutorial) perten- cem ao mesmo pacote de nome “aula”. Discutiremos isso mais adiante. 6 1 package aula; 2 3 import java.io.BufferedReader; 4 import java.io.InputStreamReader; 5 6 public class Numeros03{ 7 8 /* método principal */ 9 public static void main(String args []){ 10 BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in)); 11 try{ 12 // leitura do número inteiro 13 int num = Integer.parseInt(entrada.readLine () ); 14 // instancia um objeto de nome "verifica" da classe "Verificacao" 15 Verificacao01 verifica = new Verificacao01( num); 16 17 // verificação 01 - se o número é primo ou nã o 18 19 // Primeira Opção 20 boolean testePrimo = verifica.isPrime; 21 // em uma variável local , atribuiu o valor de um atributo da classe Verificacao01 22 if(testePrimo) 23 System.out.println(num+" é um número primo!"); 24 else 25 System.out.println("O número "+num+" não é primo!"); 26 27 // Segunda Opção 28 testePrimo = verifica.isPrimo(num); 29 // em uma variável local , atribuiu o valor de um método da classe Verificacao01 30 if(testePrimo) 31 System.out.println(num+" é um número 7 primo!"); 32 else 33 System.out.println("O número "+num+" não é primo!"); 34 35 // Terceira Opção 36 if(verifica.isPrimo(num)) // utilizou o resultado de um método da classe Verificacao01 37 System.out.println(num+" é um número primo!"); 38 else 39 System.out.println("O número "+num+" não é primo!"); 40 // fim da verificação 01 41 42 // verificação 02 - se o número é perfeito ou não 43 44 // Primeira Opção 45 boolean testePerfeito = verifica.isPerfect; 46 // em uma variável local , atribuiu o valor de um atributo da classe Verificacao01 47 if(testePerfeito) 48 System.out.println(num+" é um número perfeito!"); 49 else 50 System.out.println("Onúmero "+num+" não é perfeito!"); 51 52 // Segunda Opção 53 testePerfeito = verifica.isPerfeito(num); 54 // em uma variável local , atribuiu o valor de um método da classe Verificacao01 55 if(testePerfeito) 56 System.out.println(num+" é um número perfeito!"); 57 else 58 System.out.println("O número "+num+" não é perfeito!"); 8 59 60 // Terceira Opção 61 // utilizou o resultado de um método da classe Verificacao01 62 if(verifica.isPerfeito(num)) 63 System.out.println(num+" é um número perfeito!"); 64 else 65 System.out.println("O número "+num+" não é perfeito!"); 66 // fim da verificação 02 67 }catch(Exception erro){ 68 System.out.println("Erro de leitura!"); 69 } 70 } 71 } Código 3: Numeros03.java No código acima, têm-se diferentes formas para verificação dos tipos de números avaliados no programa. Essas três maneiras presentes em Nume- ros03.java surgem a partir do uso de uma classe para realização desta veri- ficação nomeada como Verificacao01. Como mencionado em oportunidade anterior, para fazer uso das características de uma classe é necessário a ins- tanciação de um objeto desta classe. No código anterior temos o comando: V erificacao01verifica = newV erificacao01(num); em que podemos compreender como funciona esta importante característica de uma programação orientada a objetos (POO). Na primeira parte do co- mando (antes da atribuição “=”) vemos o nome da classe seguido do nome do objeto. Por padrão, no desenvolvimento de programas em Java, uma classe tem seu nome iniciado com uma letra maiúscula e um objeto com uma letra minúscula (classe: Carro, objeto: fusca, classe: Servidor, objeto: secretario, etc.). Neste caso citado, a partir da classe Verificacao01 tem-se o objeto veri- fica. Em comparação com C, e outras linguagens imperativas, Verificacao01 funcionará como um tipo de dados e verifica como uma variável que funcione de acordo com este tipo. Mas isso ocorre com suas particularidades, como já se pode ver na segunda parte deste mesmo comando. Após o comando de atribuição temos a palavra-chave new que corres- ponde à instanciação de um objeto. Em outras palavras, cria-se um objeto 9 a partir de uma classe respeitando a estrutura desta mesma. Mas a classe pode apresentar diferentes formas de criação de seus objetos e isso é espe- cificado pelo seu método construtor (no exemplo temos Verificacao01(num) como o construtor da classe Verificacao01). A estrutura que define a classe Verificacao01 está no código a seguir. 1 package aula; 2 3 public class Verificacao01 { 4 5 public int numVerifica; // atributo de valor a ser verificado 6 public boolean isPrime; // atributo para verificar se número é primo 7 public boolean isPerfect;// atributo para verificar se número é perfeito 8 9 /* Cria uma nova instância de Verificacao01 10 * @param numero valor de entrada para verificação 11 */ 12 public Verificacao01(int numero) { 13 numVerifica = numero; 14 isPrime = isPrimo(numero); // verifica logo se o número lido é primo 15 isPerfect = isPerfeito(numero); // verifica logo se o número lido é primo 16 } 17 18 /** 19 * Método para verificação se um número é primo ou nã o 20 * @param numero valor de entrada 21 * @return verdadeiro se número é primo , falso em caso contrário 22 */ 23 public boolean isPrimo(int numero){ 24 int cont = 0; // contador do número de divisores do valor lido 25 for(int i = 1; i <= numero; i++){ 26 // se o resto desta divisão inteiro é zero , 10 então encontrou -se um divisor 27 if(numero%i == 0) 28 cont ++; 29 } 30 if(cont == 2) return true; 31 else return false; 32 } 33 34 /** 35 * Método para verificação se um número é perfeito ou não 36 * @param numero valor de entrada 37 * @return verdadeiro se número é perfeito , falso em caso contrário 38 */ 39 public boolean isPerfeito(int numero){ 40 int soma = 0; // acumulador dos divisores do valor lido 41 for(int i = 1; i < numero; i++){ 42 // se o resto desta divisão inteiro é zero , então encontrou -se um divisor 43 if(numero%i == 0) 44 soma += i; 45 } 46 if(soma == numero) return true; 47 else return false; 48 } 49 } Código 4: Verificacao01.java Com Verificacao01, transferimos os método de teste no programa prin- cipal (Numeros02.java) para uma classe com o objetivo de verificação do número lido. No código acima percebemos a presença das variáveis numVeri- fica, isPrime e isPerfect que aqui estão como atributos (como são chamados em POO) públicos, ou seja, podem ser acessados por classes externas em geral. Uma classe é formada por atributos e métodos de tal maneira que representem respectivamente os dados e comportamentos desta mesma. O uso da classe Verificacao01 permite que na classe principal (Numeros03) possamos verificar a situação do número lido por três formas: 11 a) Uso de uma variável temporária (testePrimo ou testePerfeito) para acessar o valor do atributo da classe de verificação; b) Retorno do valor obtido em um método da classe de verificação para uma variável temporária; c) Faz uso somente do retorno do valor obtido em um método da classe de verificação. O acesso direto aos atributos de uma classe não é uma boa técnica de programação em POO já que não leva em conta o encapsulamento desta classe. Isso que dizer que as classes devem se comunicar apenas através de seus métodos, já que o importante de conhecer-se em uma classe é o resultado do seu comportamento (princípio de encapsulamento, algo a ser visto nos próximos capítulos). No exemplo abaixo, verifica-se uma melhor forma de se realizar esta associação entre as classes. 1 package aula; 2 3 import java.io.*; 4 5 public class Numeros04{ 6 7 /* método principal */ 8 public static void main(String args []){ 9 BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in)); 10 try{ 11 // leitura do número inteiro 12 int num = Integer.parseInt(entrada.readLine () ); 13 // instancia um objeto de nome "verifica" da classe "Verificacao" 14 Verificacao02 verifica = new Verificacao02 (); 15 verifica.setNumVerifica(num); 16 verifica.verificaPrimo (); 17 verifica.verificaPerfeito (); 18 19 // verificação 01 - se o número é primo ou nã o 20 21 // Primeira Opção 12 22 boolean testePrimo = verifica.getIsPrime (); 23 // em uma variável local , atribuiu o valor de um método da classe Verificacao02 24 if(testePrimo) 25 System.out.println(num+" é um número primo!"); 26 else 27 System.out.println("O número "+num+" não é primo!"); 28 29 // Segunda Opção 30 if(verifica.getIsPrime ()) // utilizou o resultado de um método da classe Verificacao02 31 System.out.println(num+" é um número primo!"); 32 else 33 System.out.println("O número "+num+" não é primo!"); 34 35 // fim da verificação 01 36 37 // verificação 02 - se o número é perfeito ou não 38 39 // Primeira Opção 40 boolean testePerfeito = verifica.getIsPerfect (); 41 // em uma variável local , atribuiu o valor de um método da classe Verificacao02 42 if(testePerfeito) 43 System.out.println(num+" é um número perfeito!"); 44 else 45 System.out.println("O número "+num+" não é perfeito!"); 46 47 // Segunda Opção 48 if(verifica.getIsPerfect ()) // utilizou o resultado de um método da classe 13 Verificacao02 49 System.out.println(num+" é um número perfeito!"); 50 else 51 System.out.println("O número "+num+" não é perfeito!"); 52 53 // fim da verificação 02 54 }catch(Exception erro){ 55 System.out.println("Erro de leitura!"); 56 } 57 } Código 5: Numeros04.java No programa Numeros04.java percebe-se duas diferenças entre as imple- mentações anteriores: a) Uso de uma classe de verificação para modificação de seus atributos dentro do método principal; b) Tratamento dos atributos da classe de verificação através de seus res-pectivos métodos get e set. Após instanciar o objeto verifica a partir da classe Verificacao02, faz-se então o acesso a métodos públicos para verificação do número lido como primo ou perfeito. Depois da verificação, o programa trata os atributos de Verificacao02 através de métodos específicos para a leitura de seus valores. No código Abaixo, temos a especificação do acesso a estes atributos. 1 package aula; 2 3 public class Verificacao02 { 4 5 public int numVerifica; // atributo de valor a ser verificado 6 public boolean isPrime; // atributo para verificar se número é primo 7 public boolean isPerfect;// atributo para verificar se número é perfeito 8 9 /** Cria uma nova instância de Verificacao02 */ 14 10 public Verificacao02 () { 11 setNumVerifica (0); // corresponde a: numVerifica = 0; 12 setIsPrime(false); // corresponde a: isPrime = false; 13 setIsPerfect(false); // corresponde a: isPerfect = false; 14 } 15 16 /** 17 * Método para verificação se um número é primo ou nã o 18 */ 19 public void verificaPrimo (){ 20 int numero = getNumVerifica (); 21 int cont = 0; // contador do número de divisores do valor lido 22 for(int i = 1; i <= numero; i++){ 23 // se o resto desta divisão inteiro é zero , então encontrou -se um divisor 24 if(numero%i == 0) 25 cont ++; 26 } 27 if(cont == 2) setIsPrime(true); 28 else setIsPrime(false); 29 } 30 31 /** 32 * Método para verificação se um número é perfeito ou não 33 */ 34 public void verificaPerfeito (){ 35 int numero = getNumVerifica (); 36 int soma = 0; // acumulador dos divisores do valor lido 37 for(int i = 1; i < numero; i++){ 38 // se o resto desta divisão inteiro é zero , então encontrou -se um divisor 39 if(numero%i == 0) 40 soma += i; 15 41 } 42 if(soma == numero) setIsPerfect(true); 43 else setIsPerfect(false); 44 } 45 46 /** 47 * Retornar o número a ser verificado. 48 * @return número aplicado na verificação 49 */ 50 public int getNumVerifica (){ return numVerifica; } 51 /** 52 * Modifica o número a ser verificado. 53 * @param number número aplicado na verificação 54 */ 55 public void setNumVerifica(int number){ numVerifica = number; }; 56 57 /** 58 * Retornar o resultado da verificação de número primo. 59 * @return verdadeiro se o número é primo , falso em caso contrário 60 */ 61 public boolean getIsPrime (){ return isPrime; } 62 /** 63 * Modifica o resultado da verificação de número primo. 64 * @param novo resultado da verificação 65 */ 66 public void setIsPrime(boolean primo){ isPrime = primo; } 67 68 /** 69 * Retornar o resultado da verificação de número perfeito. 70 * @return verdadeiro se o número é perfeito , falso em caso contrário 71 */ 72 public boolean getIsPerfect (){ return isPerfect; } 73 /** 16 74 * Modifica o resultado da verificação de número perfeito. 75 * @param novo resultado da verificação 76 */ 77 public void setIsPerfect(boolean perfeito){ isPerfect = perfeito; } 78 } Código 6: Verificacao02.java Em Verificacao02.java, os atributos se mantêm públicos mas a forma de acesso a estes se diferencia da classe Verificacao01. Começando pelo constru- tor sem parâmetros: o atributo numVerifica (que guardará o valor do número a ser verificado) tem seu valor modificado a partir do método setNumVerifica. Percebe-se neste código que todos os atributos têm seus valores alterados por um método set (normalmente denominado por “set” e em seguida o nome do atributo) e também têm seus valores recuperados a partir de um método get (normalmente denominado por “get” e em seguida o nome do atributo). Esta nomeação não precisa ser tão específica (ao invés de getNumVerifica, pode-se utilizar recuperaNumVerifica) mas é a normalmente utilizada na do- cumentação de classes disponibilizadas pela Sun e outras distribuidoras de pacotes. Uma boa prática em POO é fazer uso desta maneira de acesso aos atribu- tos. Isso permite melhor controle do acesso e modificação de seus valores por outras classes e permite tratamento adequado na realização destas tarefas. A seguir pode-se reparar uma forma mais sucinta de escrever o seu código da classe principal a partir de um acesso controlado aos atributos da classe de verificação. 1 package aula; 2 3 import java.io.*;; 4 5 public class Numeros05{ 6 7 /* método principal */ 8 public static void main(String args []){ 9 BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in)); 10 try{ 11 // leitura do número inteiro 17 12 int num = Integer.parseInt(entrada.readLine () ); 13 // instancia um objeto de nome "verifica" da classe "Verificacao" 14 15 Verificacao03 verifica = new Verificacao03( num); 16 17 // verificação 01 - se o número é primo ou nã o 18 19 if(verifica.getIsPrime ()) // utilizou o resultado de um método da classe Verificacao03 20 System.out.println(num+" é um número primo!"); 21 else 22 System.out.println("O número "+num+" não é primo!"); 23 24 // fim da verificação 01 25 26 // verificação 02 - se o número é perfeito ou não 27 28 if(verifica.getIsPerfect ()) // utilizou o resultado de um método da classe Verificacao03 29 System.out.println(num+" é um número perfeito!"); 30 else 31 System.out.println("O número "+num+" não é perfeito!"); 32 33 // fim da verificação 02 34 35 }catch(Exception erro){ 36 System.out.println("Erro de leitura!"); 37 } 38 } 18 39 } Código 7: Numeros05.java A implementação da classe Numeros05 é a mais direta entre as demais. Ela apenas instancia o objeto verifica e a partir disso somente acesso o re- torno dos testes para verificar se o número é primo e/ou perfeito. Os testes da verificação ficaram totalmente internos à classe Verificacao03 e o método principal somente trabalha com retorno dos métodos de acesso a seus atri- butos. Isso fica mais claro com a especificação do código a seguir. 1 package aula; 2 3 public class Verificacao03{ 4 5 private int numVerifica; // atributo privado de valor a ser verificado 6 private boolean isPrime; // atributo privado para verificar se número é primo 7 private boolean isPerfect;// atributo privado para verificar se número é perfeito 8 9 /* Cria uma nova instância de Verificacao03 10 * @param numero valor de entrada para verificação 11 */ 12 public Verificacao03 (int numero) { 13 setNumVerifica(numero); 14 setIsPrime( isPrimo( getNumVerifica () ) ); // verifica logo se o número lido é primo 15 setIsPerfect( isPerfeito( getNumVerifica () ) ); // verifica logo se o número lido é primo 16 } 17 18 /** 19 * Método para verificação se um número é primo ou nã o 20 * @param numero valor de entrada 21 * @return verdadeiro se número é primo , falso em caso contrário 22 */ 23 public boolean isPrimo(int numero){ 19 24 int cont = 0; // contador do número de divisores do valor lido 25 for(int i = 1; i <= numero; i++){ 26 // se o resto desta divisão inteiro é zero , então encontrou -se um divisor 27 if(numero%i == 0) 28 cont ++; 29 } 30 if(cont == 2) return true; 31 else return false; 32 } 33 34 /** 35 * Método para verificação se um número é perfeito ou não 36 * @param numero valor de entrada 37 * @return verdadeiro se número é perfeito , falso em caso contrário 38 */ 39 public boolean isPerfeito(int numero){ 40 int soma = 0; // acumulador dos divisores do valor lido 41 for(int i = 1; i < numero; i++){ 42 // se o resto desta divisão inteiro é zero , então encontrou -se um divisor 43 if(numero%i == 0) 44 soma += i; 45 } 46 if(soma == numero) return true; 47 else return false; 48 } 49 50 /** 51 * Retornar o número a ser verificado. 52 * @return número aplicado na verificação 53 */ 54 public int getNumVerifica (){ return numVerifica; } 55 /** 56 * Modifica o número a ser verificado. 57 *@param number número aplicado na verificação 20 58 */ 59 public void setNumVerifica(int number){ numVerifica = number; }; 60 61 /** 62 * Retornar o resultado da verificação de número primo. 63 * @return verdadeiro se o número é primo , falso em caso contrário 64 */ 65 public boolean getIsPrime (){ return isPrime; } 66 /** 67 * Modifica o resultado da verificação de número primo. 68 * @param novo resultado da verificação 69 */ 70 public void setIsPrime(boolean primo){ isPrime = primo; } 71 72 /** 73 * Retornar o resultado da verificação de número perfeito. 74 * @return verdadeiro se o número é perfeito , falso em caso contrário 75 */ 76 public boolean getIsPerfect (){ return isPerfect; } 77 /** 78 * Modifica o resultado da verificação de número perfeito. 79 * @param novo resultado da verificação 80 */ 81 public void setIsPerfect(boolean perfeito){ isPerfect = perfeito; } 82 } Código 8: Verificacao03.java Por fim, na classe Verificacao03 temos todos os atributos agora privados. Desta forma, somente a partir dos métodos de acesso e modificação é possí- vel que outras classes trabalhem com estes atributos. Cada um possui um método get e set que são constantemente utilizados nesta classe. Nota-se isso 21 já no método construtor, em que o número a ser verificado é passado para o atributo numVerifica através do método setNumVerifica; a partir daí, com o valor retornado de getNumVerifica obtêm-se o resultado das verificações presentes nos métodos setIsPrime e setIsPerfect. Retornando a um assunto anterior: pacotes. Um pacote é um conjunto de classes reunidas para um objetivo comum. No momento em que se importa uma classe externa (através da palavra-chave import) é necessário a espe- cificação do pacote a que a classe tratada pertence. Como exemplo, temos as classes BufferedReader e InputStreamReader que pertencem ao pacote java.io. Este pacote é destinado ao tratamento de entrada/saída (input/out- put) de dados do programa, ou seja, qualquer classe pertencente ao pacote java.io terá este mesmo objetivo. Desta forma, todas as classes descritas neste material pertencem ao pacote aula. Pensando agora no acesso aos dados e comportamentos das classes já apresentadas, vejamos o seguinte exemplo: i. public int numVerifica; ii. protected int numVerifica; iii. private int numVerifica; iv. int numVerifica; Em i. o atributo numVerifica (e cada método ou outro atributo também declarado como público) será acessado por qualquer classe externa ao pacote aula. Já em ii., este mesmo atributo somente poderá ser acessado pelas clas- ses presentes na classe aula. Quando um atributo ou método é declarado como privado (no caso de iii.), este só poderá ser utilizado dentro da classe em que foi declarado. Finalmente, quando este modificador não é declarado (exemplo de iv.) não quer dizer que este não apresente um nível de acesso: em Java, quando nenhum modificador (como estes três últimos apresentados) assume-se que o atributo ou método em questão é protegido (protected). Isso indica que o tratamento em ii. e iv. funciona da mesma forma. Conclusão: Apresentaram-se aqui diferentes maneiras de escrever um mesmo código, mas focando nos benefícios de aplicar a metodologia presente em POO. Portanto, recomenda-se o uso de métodos para acesso e modificação dos atributos de 22 uma classe a fim de permitir um melhor controle na comunicação entre a nova classe criada e as demais existentes. Isso implica em descrever estes métodos como públicos e os atributos como privados. O objetivo deste material não é somente apresentar diferentes maneiras de desenvolver um mesmo problema, mas mostrar conceitos importantes que devem ser assimilados na disciplina. O foco de uma exposição como esta é permitir a visualização de uma codificação mais clara de um futuro programa na sua postura de desenvolvedor. Apostila Complementar 2 Depuração no Ambiente NetBeans Depuração, também conhecido pelo termo em inglês debugging ou debug, é o processo de encontrar e reduzir defeitos presentes num software, ou mesmo em termos de hardware. Erros de software incluem desde aqueles que previnem o programa de ser executado até aos que produzem um resultado inesperado em sua execução. Considere que as classes definidas nas Listagens 01, 02 e 03 abaixo foram implementadas no ambiente de desenvolvimento NetBeans. Este IDE permite que o código-fonte desenvolvido seja avaliado passo a passo na execução de cada linha de comando descrita a seguir. 1 package depuracao; 2 public class Un { 3 public static double somar (double x, double y){ 4 return x+y; Código 9: Descrição da classe “Un”. 1 package depuracao; 2 public class Due { 3 public static double multiplicar (double x, double y) { 4 return x*y; 5 } 6 } Código 10: Descrição da classe “Due”. Para que esta depuração seja efetuada, faz-se necessária a marcação de um ou mais pontos de parada (ou interrupção) de execução. Este ponto marca 23 24 a linha do código-fonte em que a avaliação dos comandos deve ser iniciada ou continuada. Tomemos como exemplo o código descrito na listagem que segue. 1 package depuracao; 2 import java.util.Scanner; 3 public class Depurando { 4 public static void main (String args []){ 5 double a = 14.0; 6 double b = 2.0; 7 double c = Un.somar(a, b); 8 System.out.println(c); 9 double d = Due.multiplicar(a, b); 10 System.out.println(d); 11 } 12 } Código 11: Descrição da classe “Depurando”. Caso sejam marcadas as linhas 07 e 09 da Listagem 03 na IDE (clique com botão esquerdo do mouse na numeração do código-fonte), estas indicarão onde a depuração será realizada. No exemplo identificado, foram marcados pontos de interrupção na invocação de dois métodos que estão presentes em outras classes. Ao selecionar a opção Depurar -> Depurar Arquivo (Ctrl+Shift+F5), a execução do código será interrompida na linha 07. Neste momento, a IDE exibe as variáveis que estão sendo trabalhadas na linha atual do código e seus respectivos valores. Aqui o desenvolvedor pode acompanhar o real desempenho do seu aplicativo. Caso seleciona a opção Depurar -> Continuar, a execução do programa continua e será interrompida no próximo ponto de parada (linha 09). Aqui a indicação das variáveis avaliadas e seus respectivos valores são atualizados. Mas esta avaliação do código está ligada apenas à classe demarcada (no caso, Depurando.java). É possível acessar a real execução do método indicado na depuração. Dessa maneira, duas ações são possíveis: “Passar dentro” ou “Entrar em” (“Step In”, uso da tecla F7) e “Passar sobre” ou “Ignorar” (“Step over”, uso da tecla F8). Em ambos, a execução não é interrompida apenas nas linhas marcadas. A execução segue o caminho da interpretação do código, com a execução linha por linha do código. O diferencial de “Passar dentro” em relação à outra opção, é que a execução é direcionada para a classe em 25 que se encontra o método e tem-se acesso aos valores parâmetros formais e suas atualizações baseados no que foi passado pelos parâmetros reais. Há outras variações na depuração do código no NetBeans e em outras IDEs Java, mas as principais são estas comentadas anteriormente. É possível aplicar observadores (marcações que acompanham o valor de uma variável em toda a execução do código), pausar e/ou parar a depuração, avaliar expressão lógica específica, etc. Construção e Distribuição (Arquivo JAR) No ambiente NetBeans existe o comando construir (build). Esse comando, além de compilar o programa, gerando as classes, também gera um pacote contendo todos os recursos necessários ao programa. É criado um arquivo com a extensão .JAR (Java ARchive) que pode ser executado diretamente pela JVM. Em geral, para distribuir seu programa basta enviar o JAR para seus clientes. Dentro deste podem ir imagens, sons, fontes e todos arquivos deconfiguração que forem necessários - na verdade, dentro do JAR pode ir tudo que você deseja, já que é você quem determina quais arquivos serão incluídos. Deve-se então criar um diretório novo no diretório do projeto criado. Para isso, clique sobre o nome do projeto (no NetBeans) com o botão direito do mouse e acesse o menu Novo -> Outro. Abre-se uma janela onde você deve escolher a categoria "Outro"e o Tipo de arquivo "Diretório". Clique então em Próximo e dê o nome de "res"para a pasta. Clique em Finalizar. Clique novamente com o botão direito do mouse sobre o nome do projeto e desta vez acesse o menu Propriedades. Configure a categoria Códigos-fonte conforme abaixo: 1. Pastas de pacotes de código fonte: botão Adicionar pasta...; 2. Selecione a pasta res e clique em Abrir; 3. Pastas de pacotes de testes: selecione a pasta test; 4. Clique em remover; 5. Clique em Ok; Isso faz com que o conteúdo desta pasta (arquivos e subpastas) sejam incluídos no JAR. Na pasta “res” colocaremos os recursos necessários para os 26 aplicativos, como imagens, sons, etc. Adicione o arquivo “b.png” no diretório “res” deste projeto. (a) Projeto inicial do formulário. (b) Após carregar uma imagem ex- terna. Figura 1: Interface do programa a ser distribuído. Crie um formulário JFrame com layout equivalente ao apresentado na Figura 1(a). No evento “formComponentShown” do JFrame em questão, insira o seguinte código: 1 rotulo.setText(""); 2 rotulo.setIcon(new ImageIcon("res//b.png")); // ou adicione direto na interface Código 12: Descrição do código do método "formComponentShown"de JFrame. Lembrando que o objeto “rotulo” mencionado na listagem acima, refere-se ao objeto JLabel que você tenha adicionado ao seu formulário. Execute o programa e veja se a interface gráfica resultante se assemelha à Figura 1(b). Para construir o arquivo JAR, requer-se que o projeto trabalhado seja o principal no NetBeans e que este formulário seja a classe principal do referido projeto. Tendo isso confirmado, seleciona o menu Executar -> Limpar e Construir Main Project (Shift+F11). Isso faz com o arquivo JAR do projeto seja finalmente gerado. Agora sua aplicação está pronta para ser distribuído, e pode ser simplesmente executa no cliente ao executar o arquivo JAR. 27 Formulário Interno (Projeto MDI) Em um projeto que faça uso de formulário MDI, este possui como principal característica um formulário principal que abre outros formulários em um canvas de dimensão sempre menor e interno ao seu próprio. No exemplo a seguir, criaremos um formulário principal que permitirá a chamada de um formulário interno (voltado ao modelo “Multiple Document Interface” ou MDI) e um formulário externo (modelo “Single Document Interface” ou SDI). Crie um formulário JFrame e o nomeie como FormPrincipal. Neste mesmo insira um objeto JMenuBar (barra de menu) e, dentro deste, insira dois JMe- nuItem (Item de menu). No primeiro, escreva o texto “Formulário Interno” e no segundo, “Formulário Externo”. Ainda neste mesmo formulário, insira um objeto de JDesktopPane (Painel da área de trabalho) e redimensione-o para um tamanho menor que o formulário em questão. No item de menu “Formulário Interno”, acesse o evento “actionPerformed” do mesmo com o seguinte código: 1 this.setCursor(Cursor.getPredefinedCursor(Cursor. WAIT_CURSOR)); 2 FormInterno1 addForm = new FormInterno1 (); 3 addForm.pack(); 4 addForm.setDefaultCloseOperation(JInternalFrame. DISPOSE_ON_CLOSE); 5 addForm.setResizable(false); 6 addForm.setVisible(true); 7 addForm.setSize (630 ,520); 8 addForm.setTitle("Acessando o Formulário Interno "); 9 desktopPane.add(addForm); 10 this.setCursor(Cursor.getPredefinedCursor(Cursor. DEFAULT_CURSOR)); Código 13: Descrição da chamada ao formulário interno. As linhas 01 e 10 da Listagem 05 trazem a impressão visual de que o programa está em processamento e que o mouse está desabilitado. As de- mais linhas preparam o formulário interno, que aqui é configurado como um objeto JInternalFrame. Este mesmo está ligado ao objeto desktopPane que corresponde a uma instância de JDesktopPane. O tamanho assumido pelo JDesktopPane também será configurado para qualquer outro formulário in- terno deste programa. 28 Em um formulário MDI, várias janelas internas podem ser abertas mas estas só podem ser acessadas dentro do ambiente da janela principal. Este modelo tem ficado em desuso nos últimos anos. As versões mais antigas do MS Office assumiam essa definição. Em seguida, No item de menu “Formulário Externo”, acesse o evento “actionPerformed” do mesmo com o seguinte código: 1 this.setCursor(Cursor.getPredefinedCursor(Cursor. WAIT_CURSOR)); 2 FormExterno addForm2 = new FormExterno (); 3 addForm2.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); 4 addForm2.setResizable(false); 5 addForm2.setVisible(true); 6 addForm2.setSize (630 ,520); 7 addForm2.setTitle("Adicionando um Novo Elemento"); 8 this.setCursor(Cursor.getPredefinedCursor(Cursor. DEFAULT_CURSOR)); Código 14: Descrição da chamada ao formulário externo. As linhas 02 a 06 da Listagem 06 preparam o formulário externo, que aqui é configurado como um objeto JFrame. Em um formulário SDI, várias janelas podem ser abertas com acesso independente ao ambiente da janela principal. Este modelo tem ficado substituído com sucesso o modelo MDI. As versões mais recentes do MS Office vêm assumindo essa definição. Técnicas de Programação – TD01 Inicie um novo projeto chamado de TD01. Crie o pacote de nome td01 (se não surgir automaticamente) e neste mesmo adicione duas classes nomeadas como: TestaFormas (que será a classe principal) e Ponto. Na classe Ponto, defina duas variáveis x e y correspondendo às coordenadas de um ponto real. Crie dois métodos construtores: • Um de comportamento padrão (sem argumentos), no qual os atributos recebem o valor zero; • Outro que tenha dois argumentos, e que estes mesmos atribuam os novos valores de x e y; ainda em Ponto, defina um chamado de descreveForma o qual retorna um valor String. Este valor será atribuído por uma variável interna a este método que recebe o seguinte valor: “Coordenadas do Ponto: (”+String.valueOf(x)+“, ”+String.valueOf(y)+“)”; Partindo agora para a classe principal TestaFor- mas, insira dentro do método principal os seguintes comandos: • crie um vetor de nome formas e de tipo Ponto, com três elementos na sua definição; • ao primeiro elemento do vetor, instancie um objeto Ponto a partir do construtor padrão; • ao segundo elemento do vetor, instancie um objeto Ponto a partir do construtor padrão, modifique o atributo x para assumir o valor 5 e y para assumir o valor 15; • ao terceiro elemento do vetor, instancie um objeto Ponto a partir do construtor com parâmetros, inserindo os valores 20 e 10 em, respecti- vamente, x e y. 29 30 Nesta mesma classe, crie um loop para percorrer todo o vetor formas afim de que em cada elemento, descreva a forma do mesmo (a partir do método descreveForma). Defina uma nova classe chamada Circulo, que vai herdar as caracterís- ticas de Ponto (utilize a palavra-chave extends). Defina uma variável raio correspondendo a um raio real. Crie dois métodos construtores: • um de comportamento padrão (sem argumentos), no qual o atributo raio recebe o valor zero e invoca o construtor padrão de Ponto: su- per(0,0); • outro que tenha três argumentos, e que estes mesmos atribuam o novo valor de raio e invoca o outro construtor de Ponto: super(argumento1, argumento2); ainda em Circulo, defina um chamado de descreveForma o qual retorna um valor String. Este valor será atribuído por uma variável interna a este mé- todo que recebe o seguinte valor: “Raio do Circulo: ”+String.valueOf(raio)+“, e ”+super.descreveForma(); Voltando para a classe principal TestaFormas, insira dentro do método principal (logo após as instruções definidasanteriormente) os seguintes co- mandos: crie um vetor de nome formas2 e de tipo Circulo, com três ele- mentos na sua definição; • ao primeiro elemento do vetor, instancie um objeto Circulo a partir do construtor padrão; • ao segundo elemento do vetor, instancie um objeto Circulo a partir do construtor padrão, modifique o atributo x para assumir o valor 5, y para assumir o valor 15 e o raio para assumir o valor 15; • ao terceiro elemento do vetor, instancie um objeto Circulo a partir do construtor com parâmetros inserindo os valores 30, 20 e 10 como argumentos. Nesta mesma classe, crie um loop para percorrer todo o vetor formas2 afim de que em cada elemento, descreva a forma do mesmo (a partir do método descreveForma). 31 Questão 1 Aplicar Encapsulamento nas Classes Aplique a técnica de encapsulamento nas classes Ponto e Circulo: deter- mine que os atributos destas sejam privados e os demais métodos sejam pú- blicos (inclusive os novos métodos de acesso a esses atributos encapsulados). Verifique os erros que surgem na classe TestaFormas e corrija-os de acordo com o encapsulamento das classes anteriores. Questão 2 Exercitar relacionamento de Herança entre as Classes Seguindo o raciocínio das classes Ponto e Circulo, defina uma nova classe chamada Cilindro que vai herdar as características de Circulo. Defina um atributo altura encapsulado correspondendo a uma altura real. Crie dois métodos construtores nesta mesma classe: • um de comportamento padrão (sem argumentos), no qual o atributo altura recebe o valor zero e invoca o construtor padrão de Circulo: super(0,0,0); • outro que tenha quatro argumentos, e que estes mesmos atribuam o novo valor de altura e invoca o outro construtor de Circulo: su- per(argumento1,argumento2,argumento3); ainda em Cilindro, defina um chamado de descreveForma o qual retorna um valor String. Este valor será atribuído por uma variável interna a este método que recebe o seguinte valor: “Altura do Cilindro: ” + String.valueOf(getAltura()) + “, e ”+super.descreveForma(); Volte para a classe principal TestaFormas, insira dentro do método principal (logo após as instruções definidas anteri- ormente) os seguintes comandos: • crie um vetor de nome formas3 e de tipo Ponto, com cinco elementos na sua definição; • ao primeiro elemento do vetor, instancie um objeto Ponto a partir do construtor de dois argumentos: 10 e 10; 32 • ao segundo elemento do vetor, instancie um objeto Circulo a partir do construtor de três argumentos: 5, 20 e 20; • ao terceiro elemento do vetor, instancie um objeto Cilindro a partir do construtor padrão; • ao quarto elemento do vetor, instancie um objeto Cilindro a partir do construtor de quatro argumentos: 6, 9, 10 e 12; • ao quinto elemento do vetor, instancie um objeto Ponto a partir do construtor padrão. Nesta mesma classe, crie um loop para percorrer todo o vetor formas3 afim de que em cada elemento, descreva a forma do mesmo (a partir do método descreveForma). Verifique o resultado final e tente compreender a influência da técnica de herança neste resultado. Nota: Esta lista deve ser entregue via e-mail (para: ialis@sobral.ufc.br) com todo o projeto criado compactado em arquivo com os nomes dos alunos. O trabalho que é entregue no prazo será corrigido valendo 100% em seu total. Se entregue na aula seguinte ao prazo estabelecido, o mesmo será corrigido valendo 75% do seu total. Persistindo no atraso, passa a valer apenas 50 Bom Trabalho! Técnicas de Programação – TD02 Questão 1 Pacote: td02.aleatorio Associe as classes Scanner e ArrayList para a implementação do seguinte programa: • Leia um vetor de 10 (dez) valores inteiros com a classe Scanner; • Multiplique cada valor lido a um número aleatório (Math.random()) que varie de 0 a 10000; • Insira os 04 (quatro) maiores valores do novo vetor em um objeto da classe ArrayList; • Escreva na saída o valor deste novo objeto. Questão 2 Pacote: td02.interfaceMath Pesquise sobre o uso da classe Math e implemente um programa Java (com interface gráfica) que tenha a entrada de dois números inteiros, numA e numB, e escreva a saída em valor numérico real: • Método floor aplicado em numA/numB; • Método ceil aplicado em numB/numA; • Método pow aplicado a numAnumB e numBnumA; 33 34 • Método tan aplicado a tangente de numA, numB, numA/numB e numB/- numA. Questão 3 Pacote: td02.craps Projete a interface gráfica e implemente o jogo de azar: “Craps”. Seu funci- onamento é definido da seguinte forma: • O jogador lança dois dados (cada um com seis faces, com 1, 2, 3, 4, 5 e 6 pontos respectivamente); • Calcula-se a soma das faces expostas: - Se soma = 7 ou 11 -> jogador venceu; - Se soma = 2, 3 ou 12 -> jogador perdeu; - Senão, soma torna-se a “pontuação” do jogador. • Os dados são lançados novamente: - Soma = pontuação -> jogador venceu; - Soma = 7 -> jogador perdeu; - Senão, lança os dados novamente. . Nota: Esta lista deve ser entregue via e-mail (para: ialis@sobral.ufc.br) com todo o projeto criado compactado em arquivo com os nomes dos alunos. O trabalho que é entregue no prazo será corrigido valendo 100% em seu total. Se entregue na aula seguinte ao prazo estabelecido, o mesmo será corrigido valendo 75% do seu total. Persistindo no atraso, passa a valer apenas 50 Bom Trabalho! Nota2: Os códigos de interfaceGráfica estão no Anexo I Técnicas de Programação – TD03 Questão 1 Pacote: td03.questao01 Crie sua própria exceção seguindo o modelo abaixo, em seguida construa uma função para calcular a raiz de um determinado número que gere uma exceção (cláusula throws), caso o número seja negativo, que será tratada no método principal. Ao final, independentemente do que acontecer, deve imprimir a mensagem “fim”. 1 public class NovaExcecao extends Exception { 2 public NovaExcecao () { 3 super ("Houve um novo erro!"); 4 } 5 public NovaExcecao (String msg) { 6 super (msg); 7 } 8 } // fim da classe NovaExcecao Código 15: Função Exceção(cláusula throws) Questão 2 Pacote: td03.questao02 Capturando exceções com superclasses Utilize herança para criar uma superclasse de exceção (chamada Excepti- onA) e subclasses da exceção ExceptionB e ExceptionC, em que Ex- ceptionB herda de ExceptionA e ExceptionC herda de ExceptionB. 35 36 Escreva um programa para demonstrar que o bloco catch para o tipo Ex- ceptionA captura exceções de tipos ExceptionB e ExceptionC. Questão 3 Pacote: td03.questao03 Analise o trecho de código abaixo e identifique as possíveis exceções, em seguida implemente um bloco try-catch que seja capaz de capturar todas as exceções a e imprimir uma mensagem diferente para cada uma. 1 int numero = Integer.parseInt( entrada.readLine () ); 2 int matriz [][] = {{0, 1, 2}, {3, 4}}; 3 matriz [1][2] = numero; 4 int x = 2; 5 x /= numero; 6 System.out.println("O último elemento da matriz é: "+ numero); Código 16: Código questão 3 . Nota: Esta lista deve ser entregue via e-mail (para: ialis@sobral.ufc.br) com todo o projeto criado compactado em arquivo com os nomes dos alunos. O trabalho que é entregue no prazo será corrigido valendo 100% em seu total. Se entregue na aula seguinte ao prazo estabelecido, o mesmo será corrigido valendo 75% do seu total. Persistindo no atraso, passa a valer apenas 50 Bom Trabalho! Técnicas de Programação – TD04 Este trabalho dirigido está voltado para implementação em dois novos am- bientes na disciplina: Greenfoot e Robocode. O primeiro é disponibili- zado pela própria Oracle como uma ferramenta didática (desenvolvido em University of Kent e Deakin University) para estudo da linguagem de pro- gramação Java; enquanto o segundo é um ambiente que une programação e entretenimento, projetado por Mathew A. Nelson e seus demais colaborado- res, em um jogo de batalha de robôs. Atentepara as questões a seguir, siga as instruções e comece o desenvolvimento! Questão 1 Greenfoot (http://www.greenfoot.org/) Para recordar, acompanhe material complementar (Introdução ao Greenfoot) disponível no SIGAA. Use o cenário wombats2 como base: crie suas novas classes e compare com esta implementação já pronta! Crie um cenário chamado traffic aces- sando Scenario > New: 1 - Crie uma classe chamada TrafficWorld (compare com WombatWorld) que tenha o código a seguir: 2 3 import greenfoot .*; 4 5 import java.util.Random; 6 7 /** 8 * Uma simulação de tráfego com carros e semáforos. 9 * 37 38 10 * Define o layout dos objetos no mundo. 11 */ 12 13 public class TrafficWorld extends World 14 { 15 private int x; 16 private Random randomizer = new Random (); 17 18 /** 19 * Construtor para objetos da classe TrafficWorld 20 * 21 * Cria um novo mundo com células 8x8 e com uma cé lula maior de 60x60 pixels 22 */ 23 public TrafficWorld () 24 { 25 super(9, 9, 65); 26 setBackground("sand.jpg"); 27 } 28 29 /** 30 * Povoar o mundo com um cenário fixo de carros e sem áforos. 31 */ 32 public void populate () 33 { 34 RedCar rc = new RedCar (); 35 addObject(rc, 4, 0); // posiciona o objeto por [ coluna ,linha] 36 37 GreenCar gc = new GreenCar (); 38 addObject(gc, 4, 8); 39 40 BlueCar bc = new BlueCar (); 41 addObject(bc, 0, 4); 42 43 Ambulance ambulance = new Ambulance (); 44 addObject(ambulance , 4, 4); 45 46 TrafficLight tl1 = new TrafficLight (); 39 47 addObject(tl1 , 0, 1); 48 49 TrafficLight tl2 = new TrafficLight (); 50 addObject(tl2 , 8, 1); 51 52 TrafficLight tl3 = new TrafficLight (); 53 addObject(tl3 , 0, 7); 54 55 TrafficLight tl4 = new TrafficLight (); 56 addObject(tl4 , 8, 7); 57 58 TrafficLight tl5 = new TrafficLight (); 59 addObject(tl5 , 4, 1); 60 61 TrafficLight tl6 = new TrafficLight (); 62 addObject(tl6 , 4, 7); 63 64 TrafficLight tl7 = new TrafficLight (); 65 addObject(tl7 , 4, 4); 66 } 67 68 /** 69 * Liga e desliga as luzes no semáforo apresentado. 70 * 71 * @param numLights numero de semáfotos que são inseridos no mundo 72 */ 73 public void randomLights(int numLights) 74 { 75 for(int i=0; i<numLights; i++) { 76 TrafficLight tl = new TrafficLight (); 77 int x = Greenfoot.getRandomNumber(getWidth ()) ; 78 int y = Greenfoot.getRandomNumber(getHeight () ); 79 addObject(tl, x, y); 80 } 81 } 82 } 83 - Crie uma classe chamada Car que tenha o código a 40 seguir: 84 import greenfoot .*; // imports Actor , World , Greenfoot , GreenfootImage 85 86 /** 87 * Car - uma classe para representar carros. 88 */ 89 90 public class Car extends Actor 91 { 92 private static final int EAST = 0; 93 private static final int WEST = 1; 94 private static final int NORTH = 2; 95 private static final int SOUTH = 3; 96 97 private int direction; 98 99 private GreenfootImage carRight; 100 private GreenfootImage carLeft; 101 102 /** 103 * Construtor para objetos de classe Car 104 */ 105 public Car() 106 { 107 carRight = getImage (); 108 carLeft = new GreenfootImage(getImage ()); 109 carLeft.mirrorHorizontally (); 110 111 setDirection(EAST); 112 } 113 114 /** 115 * Indica qual direção o carro se movimenta. 116 */ 117 public void act() 118 { 119 // descreva este código 120 } 121 41 122 /** 123 * Checa se há um semáforo na mesma célula em que o carro está. 124 */ 125 public boolean foundTrafficLight () 126 { 127 // descreva este código 128 } 129 130 /** 131 * Verifica o semáforo e decide o que o carro deve fazer. 132 */ 133 public void verifyTrafficLight () 134 { 135 // descreva este código 136 } 137 138 /** 139 * Move uma célula à frente na direção atual. 140 */ 141 public void move() 142 { 143 // descreva este código 144 } 145 146 /** 147 * Testa se pode mover adiante. 148 * Retorna true se pode mover , false em caso contrá rio. 149 */ 150 public boolean canMove () 151 { 152 // descreva este código 153 } 154 155 /** 156 * Toma uma direção aleatória. 157 */ 158 public void turnRandom () 42 159 { 160 // descreva este código 161 } 162 163 /** 164 * Direciona pra esquerda. 165 */ 166 public void turnLeft () 167 { 168 // descreva este código 169 } 170 171 /** 172 * Modifica a direção a ser seguida. 173 */ 174 public void setDirection(int direction) 175 { 176 // descreva este código 177 } 178 } 179 - Crie uma classe chamada BlueCar (compare com Wombat) que tenha o código a seguir: 180 import greenfoot .*; // imports Actor , World , Greenfoot , GreenfootImage 181 182 /** 183 * BlueCar - uma classe para representar qualquer carro azul. 184 * 185 */ 186 187 public class BlueCar extends Car 188 { 189 190 /** 191 * Construtor para objetos da classe BlueCar 192 */ 193 public BlueCar () 194 { 195 } 43 196 197 /** 198 * Indica qual direção o carro azul se movimenta. 199 */ 200 public void act() 201 { 202 // descreva este código 203 } 204 205 /** 206 * Verifica o semáforo e decide o que o carro azul pode fazer. Dobrar à direita , preferencialmente! 207 */ 208 public void verifyTrafficLight () 209 { 210 // descreva este código 211 } 212 213 } 214 - Crie uma classe chamada Ambulance (compare com Wombat) que tenha o código a seguir: 215 import greenfoot .*; // imports Actor , World , Greenfoot , GreenfootImage 216 217 /** 218 * Ambulance - uma classe para representas as ambulâncias . 219 * 220 */ 221 222 public class Ambulance extends Car 223 { 224 225 /** 226 * Construtor para objetos da classe Ambulance 227 */ 228 public Ambulance () 229 { 230 } 231 44 232 /** 233 * Indica qual direção a ambulância se movimenta. 234 */ 235 public void act() 236 { 237 // descreva este código 238 } 239 240 /** 241 * Não verifica o semáforo e a ambulância segue seu caminho. 242 */ 243 public void verifyTrafficLight () 244 { 245 // nenhum semáforo deve ser considerado! - prioridade no tráfego para a ambulância ... 246 // descreva este código 247 } 248 } 249 - Crie uma classe chamada TrafficLight (compare com Rock e Leaf) que tenha o código a seguir: 250 import greenfoot .*; // imports Actor , World , Greenfoot , GreenfootImage 251 252 /** 253 * TrafficLight - uma classe para representar semáforos. 254 * 255 */ 256 257 public class TrafficLight extends Actor 258 { 259 private int counter; 260 private boolean freePassage; 261 262 /** 263 * Construtor para objetos da classe TrafficLight 264 */ 265 public TrafficLight () 266 { 267 setCounter (0); 45 268 /* Math.round(Math.random ()*1) - returns 0 or 1 269 * if equals to 0 -> red light 270 * if equals to 1 -> green light 271 */ 272 if(Math.round(Math.random ()*1) == 0) 273 { 274 setFreePassage(false); 275 setImage("semaphore -closed.gif"); 276 } 277 else 278 { 279 setFreePassage(true); 280 setImage("semaphore -opened.gif"); 281 } 282 } 283 284 /** 285 * Liga/desliga o semáforo. 286 */ 287 public void act() 288 { 289 setCounter(getCounter ()+1); 290 if(getCounter ()%20 == 0) // atualiza o status do semáforo para cada vinte rodadas 291 { 292 if(getFreePassage ()) 293 { 294 setFreePassage(false); 295 setImage("semaphore -closed.gif"); 296 } 297 else 298 { 299 setFreePassage(true); 300 setImage("semaphore -opened.gif"); 301 } 302 } 303 } 304 305 /** 306 * Modifica o valor do contador que é relacionado ao 46 semáforo. 307 * 308 * @param value novo valor do contador 309 */ 310 public void setCounter(int value) 311 { 312 this.counter = (value >= 0 ? value : 0); 313 } 314 315 /** 316 * Recupera o valor do contador que é relacionado ao semáforo. 317 * 318 * @return o valor atual do atributo contador 319 */ 320 public int getCounter () 321 { 322 returnthis.counter; 323 } 324 325 /** 326 * Modifica o valor de freePassage que indica quando um carro pode passar direto. 327 * 328 * @param status novo status do semáforo 329 */ 330 public void setFreePassage(boolean status) 331 { 332 this.freePassage = status; 333 } 334 335 /** 336 * Recupera o status do semáforo. 337 * 338 * @return status do semáforo 339 */ 340 public boolean getFreePassage () 341 { 342 return this.freePassage; 343 } 47 344 } Código 17: Código do Cenário traffic Figura 2: Tela principal a ser projetada. Questão 2 Robocode Para saber um pouco mais sobre o ambiente Robocode e como desenvolver seus protótipos no mesmo, acompanhe material complementar (Curso para Jovens Programadores) disponível no SIGAA. Inicie o programa Robocode. Verifique no menu Battle a opção Open. Abra então o arquivo sample disponível e inicie a escolha dos robôs que 48 participarão da batalha a ser iniciada: selecione com o mouse no campo Robots (e veja sua descrição no texto que surge abaixo da tela) e clique em Add quando for um robô de interesse. Quando quiser iniciar a batalha, clique no botão Start Battle (quer coisa mais intuitiva que essa?). Então é só ver o resultado da batalha de robôs iniciada! Agora é a sua vez de preparar um robô para a batalha! Na tela inicial do Robocode, acesse o menu Robot e entre na opção Editor. Dentro do editor de robôs, siga para o menu File > New > Robot. Nomeie o seu robô e o pacote a qual ele deve pertencer. Para ajudar na sua implementação acesse: File > Open. Abra o código de quaisquer robôs já disponíveis nesse ambiente e utilize os códigos visualizados no seu desenvolvimento. Crie um robô diferenciado dos que já existem (com características novas ou mesclando comportamentos já existentes em outros robôs) e envie até o prazo definido. Seu protótipo será desafiado pelos robôs desenvolvidos pelos seus colegas de turma. Boa sorte! Nota: Os Trabalhos Dirigidos (TD) são desenvolvidos em laboratório du- rante uma aula de 100 (cem) minutos. A implementação dos trabalhos é realizada em dupla, com o revezamento do aluno que será responsável pela digitação e o que apresentará o resultado. Cada TD terá uma nota específica mencionada no início da aula. Bom Trabalho! Técnicas de Programação - TD05 Questão 1 pacote: td05.testeJTable Observe a figura que segue: Figura 3: Tela principal a ser projetada. Desenvolva uma classe para produzir a mesma interface gráfica apresen- tada na Figura 3. Pode-se observar os seguintes componentes gráficos pre- 49 50 sentes nela. Crie uma classe chamada DelForm que utilize interface gráfica. • Na janela a ser criada deve-se utilizar um componente da classe JMe- nuBar (Barra de Menu); – Na paleta Inspector (lado esquerdo da tela) pode-se adicionar com- ponentes ligados a essa classe: ∗ Adicione dois componentes JMenu (Menu), um com nome “Arquivo” e o outro com “Ajuda”; ∗ No primeiro JMenu adicione 3 (três) JMenuItem’s (Itens de Menu) com os textos: “Adicionar Elemento”, “Remover Ele- mento” e “Sair”. Adicione um componente JSeparator (Sepa- rador) entre o segundo e terceiro JMenuItem; ∗ No segundo JMenu adicione 2 (dois) JMenuItem’s: “Con- teúdo” e “Sobre”. ∗ No JMenuItem relacionado ao texto “Sair”, selecione o evento actionPerformed e defina o comando: System.exit(0); • Finalize a interface gráfica que está sendo proposta! Defina o compo- nente JFrame com o layout de borda e siga: – Insira dois painéis (um ao Centro e seguindo o layout de borda, e o outro direcionado ao Sul e com layout de fluxo), ∗ No primeiro painel, adicione um componente JTable (Tabela, normalmente vem ligado a um componente JScrollPane). Este mesmo painel deve apresentar o seguinte título na borda: “Lis- tagem dos Elementos: ”; ∗ No segundo painel, adicione dois botões: o primeiro deve ter o texto “Excluir” (seu código será descrito posteriormente) e o último deve ter o texto “Fechar”. No botão Fechar, insira no evento actionPerformed o comando: this.dispose(); 51 • Utilizando o NetBeans, já será acrescentado um método construtor. Dentro deste deve ser chamado o método initInterface(). – Defina atributos privados na classe, relacionado a: ∗ um objeto da classe ElementoTableModel (passada em anexo a este TD); ∗ um vetor de Strings (String[]), que indicará os termos das colunas da tabela; ∗ um objeto de ArrayList, que carregará os dados da tabela; – Crie então um método privado nomeado como initInterface; ∗ Neste método inicie configurando o cur- sor para ficar em modo de espera: this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); ∗ inicie um tratamento de exceção: ∗ o objeto das colunas deve ser inicializado com: new String[] “Símbolo”, “Nome”, “Num. Atômico”, “Massa Atômica”, “Num. de Períodos”, “Família”, “” ∗ adicione os seguintes dados no objeto de ArrayList: · “H”, “Hidrogênio”, “elements/h.png”, “1”, “1.008”, “1”, “1” · “He”, “Hélio”, “elements/he.png”, “2”, “4.003”, “1”, “18” · “Li”, “Lítio”, “elements/li.png”, “3”, “6.941”, “2”, “1” · “Be”, “Berílio”, “elements/be.png”, “4”, 9.012”, “2”, “2” · “B”, “Boro”, “elements/b.png”, “5”, “10.81”, “2”, “13” · “C”, “Carbono”, “elements/c.png”, “6”, “12.01”, “2”, “14” ∗ o objeto do modelo de tabela deve ser instanciado com: new ElementoTableModel(dados, colunas); sendo dados os valores da tabela e colunas as strings passadas em array. ∗ com o método setModel configure o modelo do objeto de JTa- ble; 52 • – ∗ Torne a coluna de ID_Index (presente no modelo) deve ser oculta (isso será importante para práticas futuras!). Modifique-a da seguinte forma: · instancie um objeto TableColumn, para fa- zer esta modificação, como segue: Ta- bleColumn escondida = objetoDeJTa- ble.getColumnModel().getColumn(ElementoTableModel.ID INDEX); · modifique a largura mínima, preferida e máxima com os métodos, respectivamente, setMinWidth, setPrefer- redWidth e setMaxWidth, sendo todas com o argumento 2; ∗ redesenhe o objeto da tabela com o método repaint(); ∗ modifique as dimensões (630x520) e localização (320,120) da tela a ser criada; ∗ encerre o tratamento de exceção, no caso sobre NullPointe- rException. ∗ Configure cursor para voltar ao estado normal: this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT _CURSOR)); – No evento actionPerformed do botão relacionado a ação de “Ex- cluir” deve-se inserir os seguintes comandos: ∗ inicie um tratamento de exceção: ∗ armazena uma variável do tipo inteiro com o índice da linha selecionada: linha = tabElemento.getSelectedRow(); ∗ armazene em uma variável do tipo String, o valor do índice do item escolhido na tabela a partir do comando: ∗ armazene em outra variável do tipo String, o valor do número atômico do item escolhido na tabela a partir do comando: tabElemento.getValueAt(linha,modelo.NUMERO_ATOMICO _INDEX).toString() ∗ remova a linha do objeto de modelo da tabela com o mé- todo removeRow, tendo como argumentos o valor do índice do item escolhido e o valor da coluna deste mesmo índice (modelo.ID_INDEX); 53 • – ∗ crie novamente um objeto da classe TableColumn para ajustar a reconfiguração da tabela após a remoção da linha: · lembre-se de configurar a largura mínima, preferida e má- xima desta coluna! ∗ exiba uma caixa de diálogo informando que o elemento foi removido da tabela; ∗ retire o foco do botão de exclusão com o método grabFocus(); ∗ encerre o tratamento de exceção, no caso sobre ArrayInde- xOutOfBoundsException. 54 ANEXO I - Códigos TD 02 Códigos de interface gráfica Alô Mundo 1 package aula.igrafica; 2 3 import javax.swing.JFrame; import javax.swing.JOptionPane ; 4 5 public class AloMundo extends JFrame { 6 /** Creates a new instance of AloMundo */ 7 public AloMundo (){ 8 JOptionPane.showMessageDialog(null ,"Alô, mundo!","Primeiro programa com interface gráfica", JOptionPane.DEFAULT_OPTION); 9 } 10 public static void main(String args []){ 11 AloMundo aplicacao = new AloMundo (); 12 aplicacao.setDefaultCloseOperation(JFrame. EXIT_ON_CLOSE); 13 } 14 } Código 18: AloMundo.java 55 56 Calculadora 1 package aula.igrafica; 2 3 import javax.swing .*; 4 5 public class Calculadora extends JFrame { 6 public Calculadora () { 7 try{ 8 String opcao = JOptionPane.showInputDialog(null ," Defina uma operação a ser realizada :\n" + "1 - para adição\n2 - para subtração\n3 - para multiplicação\n" + "4 - para divisão inteir"," Agora é o segundo programa! ;-)",JOptionPane. QUESTION_MESSAGE); 9 char opc = opcao.trim().charAt (0); 10 switch(opc){ 11 case ’1’:case ’2’:case ’3’:case ’4’: 12 opcao = JOptionPane.showInputDialog(null ," Qual o primeiro numero inteiro da operação ?","Tá indo bem!",JOptionPane. QUESTION_MESSAGE); 13 int num1 = Integer.parseInt(opcao); 14 opcao = JOptionPane.showInputDialog(null ," Qual o segundo numero inteiro da operação? ","Continua indo bem!",JOptionPane. QUESTION_MESSAGE); 15 int num2 = Integer.parseInt(opcao); 16 int resultado = 0; 17 if(opc == ’1’) 18 resultado = num1+num2; 19 else{ 20 if(opc == ’2’) 21 resultado = num1 -num2; 22 else{ 23 if(opc == ’3’) 24 resultado = num1*num2; 25 else 26 resultado = num1/num2; 27 } 57 28 } 29 JOptionPane.showMessageDialog(null ,"O resultado final é: "+resultado ,"Olha as coisas melhorando ...",JOptionPane. INFORMATION_MESSAGE); 30 break; 31 default: 32 JOptionPane.showMessageDialog(null ,"Voce digitou um valor não trabalhado!"," Primeira mensagem de erro",JOptionPane. ERROR_MESSAGE); 33 break; 34 } 35 }catch(Exception e){ 36 JOptionPane.showMessageDialog(null ,"Travou foi tudo!","Mais uma mensagem de erro",JOptionPane .ERROR_MESSAGE); 37 } 38 } 39 public static void main(String args []){ 40 Calculadora aplicacao = new Calculadora (); 41 aplicacao.setDefaultCloseOperation(JFrame. EXIT_ON_CLOSE); 42 } 43 } Código 19: Calculadora.java 58 Teste Label 1 2 package aula.igrafica; 3 4 import java.awt.*; import javax.swing .*; 5 6 public class TesteLabel extends JFrame { 7 private JLabel label1 , label2 , label3; 8 public TesteLabel () { 9 super("Teste Label!"); 10 Container container = getContentPane (); container .setLayout( new FlowLayout () ); 11 label1 = new JLabel("Label com texto"); label1. setToolTipText("Este é o label1"); container. add( label1 ); 12 Icon duke = new ImageIcon("duke.gif"); 13 label2 = new JLabel("Label com texto e ícone", duke ,SwingConstants.LEFT); 14 label2.setToolTipText("Este é o label2"); 15 container.add( label2 ); 16 label3 = new JLabel (); 17 label3.setText("Label com texto"); 18 label3.setIcon(duke); 19 label3.setHorizontalTextPosition( SwingConstants. CENTER ); 20 label3.setVerticalTextPosition( SwingConstants. BOTTOM ); 21 label3.setToolTipText("Este é o label3"); 22 container.add( label3 ); 23 setSize (375 ,270); 24 setVisible(true); 25 } 26 public static void main(String args []){ 27 TesteLabel aplicacao = new TesteLabel (); 28 aplicacao.setDefaultCloseOperation(JFrame. EXIT_ON_CLOSE); 29 } 30 } Código 20: TesteLabel.java 59 Flow Layout Demo 1 package aula.igrafica; 2 3 import java.awt.*; 4 import java.awt.event .*; 5 import javax.swing .*; 6 7 public class FlowLayoutDemo extends JFrame { 8 private JButton leftButton , centerButton , rightButton ; 9 private Container container; 10 private FlowLayout layout; 11 public FlowLayoutDemo () { 12 super("FlowLayoutDemo"); 13 layout = new FlowLayout (); 14 container = getContentPane (); 15 container.setLayout( layout ); 16 17 leftButton = new JButton("Esquerda"); 18 leftButton.addActionListener( 19 new ActionListener () { 20 public void actionPerformed(ActionEvent event){ 21 layout.setAlignment(FlowLayout.LEFT); 22 layout.layoutContainer(container); 23 } 24 } 25 ); 26 container.add(leftButton); 27 centerButton = new JButton("Centro"); 28 centerButton.addActionListener( 29 new ActionListener () { 30 public void actionPerformed(ActionEvent event){ 31 layout.setAlignment(FlowLayout.CENTER ); 32 layout.layoutContainer(container); 33 } 34 } 60 35 ); 36 container.add(centerButton); 37 38 rightButton = new JButton("Direita"); 39 rightButton.addActionListener( 40 new ActionListener () { 41 public void actionPerformed(ActionEvent event){ 42 layout.setAlignment(FlowLayout.RIGHT) ; 43 layout.layoutContainer(container); 44 } 45 } 46 ); 47 container.add(rightBut ton); 48 setSize (300 ,75); 49 setVisible(true); 50 } 51 public static void main(String args []){ 52 FlowLayoutDemo aplicacao = new FlowLayoutDemo (); 53 aplicacao.setDefaultCloseOperation(JFrame. EXIT_ON_CLOSE); 54 } 55 } Código 21: FlowLayoutDemo.java 61 Border Layout Demo 1 2 package aula.igrafica; 3 4 import java.awt.*; 5 import java.awt.event .*; 6 import javax.swing .*; 7 8 public class BorderLayoutDemo extends JFrame implements ActionListener { 9 private JButton buttons []; 10 private String names[] = {"Oculta Norte","Oculta Sul" ,"Oculta Leste","Oculta Oeste","Oculta Centro"}; 11 private BorderLayout layout; 12 public BorderLayoutDemo () { 13 super("BorderLayoutDemo"); 14 layout = new BorderLayout (); 15 Container container = getContentPane (); 16 container.setLayout( layout ); 17 18 buttons = new JButton[names.length ]; 19 20 for(int count = 0; count < names.length; count ++) { 21 buttons[count] = new JButton(names[count ]); 22 buttons[count]. addActionListener(this); 23 } 24 container.add(buttons [0], BorderLayout.NORTH); 25 container.add(buttons [1], BorderLayout.SOUTH); 26 container.add(buttons [2], BorderLayout.EAST); 27 container.add(buttons [3], BorderLayout.WEST); 28 container.add(buttons [4], BorderLayout.CENTER); 29 30 setSize (300 ,200); 31 setVisible(true); 32 } 33 34 public void actionPerformed(ActionEvent event){ 35 for(int count = 0; count < buttons.length; count 62 ++){ 36 if(event.getSource () == buttons[count]) 37 buttons[count]. setVisible(false); 38 else 39 buttons[count]. setVisible(true); 40 } 41 layout.layoutContainer( getContentPane () ); 42 } 43 public static void main(String args []){ 44 BorderLayoutDemo aplicacao = new BorderLayoutDemo (); 45 aplicacao.setDefaultCloseOperation(JFrame. EXIT_ON_CLOSE); 46 } 47 } Código 22: BorderLayoutDemo.java 63 Grid Layout Demo 1 2 package aula.igrafica; 3 4 import java.awt.*; 5 import java.awt.event .*; 6 import javax.swing .*; 7 8 public class GridLayoutDemo extends JFrame implements ActionListener { 9 private JButton buttons []; 10 private String names[] = {"um","dois","três","quatro" ,"cinco"}; 11 private GridLayout grid1 , grid2; 12 private boolean alternador = true; 13 private Container container; 14 15 public GridLayoutDemo () { super("GridLayoutDemo"); 16 grid1 = new GridLayout (2,3,5,5); grid2 = new GridLayout (3,2); 17 container = getContentPane (); container.setLayout (grid1); 18 buttons = new JButton[names.length ]; 19 for(int cont = 0; cont < names.length; cont ++){ 20 buttons[cont] = new JButton(names[cont]); 21 buttons[cont]. addActionListener(this); 22 container.add(buttons[cont]); 23 } setSize (300 ,150); setVisible(true); 24 } 25 public void actionPerformed(ActionEvent event){ 26 if(alternador) 27 container.setLayout(grid2); 28 else 29 container.setLayout(grid1); 30 alternador = !alternador; container.validate (); 31 } 32 public static void main(String args []){ 33 GridLayoutDemo aplicacao = new GridLayoutDemo (); 34 aplicacao.setDefaultCloseOperation(JFrame. 64 EXIT_ON_CLOSE); 35 } 36 } Código 23: GridLayoutDemo.java
Compartilhar