Pensamento Computacional - Métodos no Java

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar

Objetivos da Aula

  • Conceituar métodos, parâmetros e valor de retorno no Java;
  • Definir, declarar e chamar métodos no Java;
  • Aplicar métodos para resolver subproblemas de um grande problema;

O que é um método no Java

Uma método (também pode ser visto como uma função) é um "bloco de código" que resolve um dado problema
específico,  que possui um nome associado e 
que pode ser chamado quando necessário. Ao final da execução
do código do método, o fluxo de execução retorna para quem "chamou" o método.  
Exemplo: para calcular o seno de um ângulo chamamos um método para resolver 
o problema específico: "calcular um seno". Dados de entrada devem ser fornecidos,
no caso o ângulo. O dado de saída é o seno computado deste ângulo.
Notar que a função permite REAPROVEITAR o código. Não precisamos a todo momento
reescrever um código que computa o seno. Basta chamar a função.

EXEMPLO: Desenhar um retângulo no terminal exige um certo número de linhas de código. É uma tarefa bem específica que poderia ser "ENCAPSULADA" em um método. Seria algo da forma:

import java.util.Scanner;

public class MetodoDesenhaRetangula {

    public static void DesenhaRetangulo() {

        for(int i = 0; i < 10; i++ ) {        
            for(int j = 0; j < 20; j++ ) {
                System.out.print("X");
            }
            System.out.println("");             
        }

        System.out.println("");         
    }

    public static void main(String[] args) {
        System.out.println("Vou desenhar um retangulo...");
        DesenhaRetangulo();  
        System.out.println("Vou desenhar um outro retangulo...");
        DesenhaRetangulo();                
    }

}

DISCUSSÃO: Neste exemplo existem dois métodos: o main() e DesenhaRetangulo(). Podemos dizer que ao executar o programa, o método main() é AUTOMATICAMENTE chamado. Uma após outra, as instruções do método main() são executadas. Inicialmente a instrução:

 System.out.println("Vou desenhar um retangulo...");

Esta instrução é uma CHAMADA ao método println()... Este método está na biblioteca e tem como objetivo imprimir mensagens na tela.

Na sequência é executada a seguinte instrução:

         DesenhaRetangulo();

Esta instrução TAMBÉM é uma chamada de um método. OBSERVE o significado de CHAMAR: é o desvio do fluxo de execução do programa para o código do método. O código será executado até o final quando então o fluxo de execução retorna para QUEM/QUE chamou.

Observe que a implementação do método DesenhaRetângulo() foi fornecida pelo próprio programador. Já o método println() já está implementado na biblioteca.

Após a chamada do DesenhaRetângulo(), novamente é chamado o método println:

          System.out.println("Vou desenhar um outro retangulo...");

E finalmente é chamado mais uma vez o método DesenhaRetangulo();.

 Trata-se de um exemplo simples mostrando que podemos chamar quantas vezes quisermos um determinado código de um método.

Parâmetros de um método

No exemplo anterior, o método DesenhaRetangulo() cumpre bem a sua tarefa de desenhar um retângulo. Entretanto, o que podemos fazer se desejarmos configurar o número de linhas e a largura do retângulo?

Aqui entra o conceito de PARAMETRIZAR o método, ou seja, repassar valores para que ele possa ser PERSONALIZADO ("customized" em inglês).

Vamos a um exemplo onde PARAMETRIZAMOS a LARGURA do retângulo:

import java.util.Scanner;

public class MetodoDesenhaRetangula {

    public static void DesenhaRetanguloLarguraConfiguravel(int largura) {

        for(int i = 0; i < 10; i++ ) {        
            for(int j = 0; j < largura; j++ ) {
                System.out.print("X");
            }
            System.out.println("");             
        }

        System.out.println("");         
    }

    public static void main(String[] args) {
        System.out.println("Vou desenhar um retangulo...");
        DesenhaRetanguloLarguraConfiguravel(10);  
        System.out.println("Vou desenhar um outro retangulo...");
        DesenhaRetanguloLarguraConfiguravel(20);                
    }

}

DISCUSSÃO: Agora conseguimos repassar a largura que queremos ao chamar o método DesenhaRetanguloLarguraConfiguravel(). Observe que o valor repassado (no caso 10) é COPIADO para o parâmetro FORMAL largura, ANTES do método ser chamado ("invoked" em inglês). Desta forma, quando o código do método começa a ser executado, o parâmetro largura conterá o valor 10. Observe que "largura" é uma variável especial que serve como interface entre QUEM CHAMA e o CHAMADO.

Sintaxe do método com PARÂMETROS

Observe que os parâmetros são declarados dentro de parênteses, tal como se fossem variáveis. Vamos modificar o código acima para que sejam passados dois parâmetros: largura e altura:

import java.util.Scanner;

public class MetodoDesenhaRetangula {

    public static void DesenhaRetanguloLarguraConfiguravel(int largura, int altura) {

        for(int i = 0; i < altura; i++ ) {        
            for(int j = 0; j < largura; j++ ) {
                System.out.print("X");
            }
            System.out.println("");             
        }

        System.out.println("");         
    }

    public static void main(String[] args) {
        System.out.println("Vou desenhar um retangulo...");
        DesenhaRetanguloLarguraConfiguravel(10, 10);  
        System.out.println("Vou desenhar um outro retangulo...");
        DesenhaRetanguloLarguraConfiguravel(20, 15);                
    }

}

O detalhe de como é realizada a chamada e passagem de parâmetros é mostrada abaixo. Em vermelho, mostrando a cópia de valores para os parâmetros formais largura e altura.

JavaDetalheChamadaParametros.png

Exercício 1

Implemente no método main() um código que lê pelo teclado os valores da altura e largura desejada do retângulo. Na sequência o método de desenho de retângulo deve ser chamado com os valores lidos.

Exercício 2

O problema resolvido pelo método de desenho de retângulo poderia ainda ser decomposto no desenho de linha. Crie um método de desenho de linha e chame-o a partir do método de desenho de retângulo.

Valor de Retorno de um Método

Os parâmetros do método podem ser vistos como DADOS DE ENTRADA para o código do método. Em várias situações o método pode produzir um valor que deverá ser RETORNADO para o código que chamou. Vamos a um exemplo simples de um método para computar a média de 3 números:

PROBLEMA> Computar a média de 3 números reais. DADOS DE ENTRADA (parâmetros): os 3 números SAÍDA: média computada

import java.util.Scanner;

public class MediaTresNumeros {

    public static double mediaTresNumeros(double  num1, double num2, double num3) {
        double mediaCalculada;

        mediaCalculada = (num1 + num2 + num3) / 3;

        return mediaCalculada;
    }

    public static void main(String[] args) {
        double media;
        System.out.println("Vou calcular a media de 3 números...");
            
        media = mediaTresNumeros ( 10.5, 9.5, 10.0 );
        System.out.println("Media de 10.5, 9.5 e 10.0 é " + media);
    }

}

DISCUSSÂO: Este exemplo é puramente didático. Possivelmente não se justificaria um método para este cálculo. O método aceita os 3 parâmetros de entrada e retorna o valor da média calculada. Observe que em termos de fluxo de execução, um método sempre retorna (pelo menos os "bem comportados"). Entretanto, neste caso acompanha um VALOR de retorno que é o resultado do processamento. Este resultado, em geral, deverá ser armazenado em algum local, no caso, na variável media do método chamador (main()).

Sintaxe associada ao retorno

Um ponto interessante a ser observado é que na implementação do método, o TIPO DE RETORNO deve ser informado. Se não retornar valor então será usada a palavra reservada "void". Confira nos exemplos de desenho de retângulo, onde não era retornado nenhum valor. Se o método retorna um valor, então o TIPO DE RETORNO é explicitado. Veja o detalhe:

JavaValorDeRetorno.png

DISCUSSÃO: Observe que o método de cálculo de média usa a instrução 'return' acompanhada do valor a ser retornado, no caso, o conteúdo da variável 'mediaCalculada'. Normalmente esta instrução está no final do método, mas não necessariamente. Podem existir inclusive várias instruções 'return' em um mesmo método.

Exercício 3

Implemente um método Java para cálculo da área de um círculo. Quais seriam os parâmetros deste método? Qual seria o valor de retorno?

Exercício 4

Implemente um método Java para cálculo da área de um anel composto por dois círculos. Reutilize o método acima. Quais seriam os parâmetros deste método? Qual seria o valor de retorno?

Exercício 5

Implemente um método Java para computar o fatorial de um número. Quais seriam os parâmetros deste método? Qual seria o retorno? No programa principal, mostre em uma única instrução como seria a computação da soma de dois fatoriais:

Variáveis locais ao método e variáveis globais (dentro da classe)

Variáveis declaradas no bloco de código do método são LOCAIS no sentido que são "vistas" somente pelo código do método. O tempo de vida destas variáveis é o tempo em que a o método se executa. Assim que houver um retorno para quem chamou (invocou), esta variável deixa de existir.

DISCUSSÃO: No exemplo acima observe que a variável mediaCalculada é declarada dentro do método MediaTresNumeros(). Desta forma, o método main() não "enxerga" esta variável, que somente será criada quando o método for invocado e destruída quando o método retornar.

É interessante observar que a variável media, declarada dentro do main() também é uma variável local. Como o método main() é invocado pelo "sistema" quando o programa começa a ser executado, esta variável tem um tempo de vida correspondente ao tempo em que o programa se executa, sendo destruída quando o main() retorna.

Na realidade, este conceito de variáveis locais se estende a qualquer bloco, ou seja, uma variável pode ser declarada dentro de qualquer bloco começando e terminando com chaves.

Também é possível declarar variáveis fora dos métodos e dentro da classe. O exercício abaixo trabalha esta ideia: as variáveis:

   String senha1, msgUsuario1;
   String senha2, msgUsuario2;
   Scanner teclado;

são "vistas" por todos os métodos encapsulados na classe. Podemos dizer que estas variáveis são globais em relação aos métodos da classe. O ideal é sempre reduzir ao máximo este tipo de variável pois reduz a coesão do método.

Exercício 6

Considere o seguinte problema (já repassado em avaliação): Um sistema de controle de acesso a um ambiente permite cadastrar 2 passwords (senhas) de usuários. Para acesso ao ambiente basta entrar com uma destas passwords que uma porta se abre. Uma password adicional permite entrar em modo administrador. Esta senha é imutável e registrada na caixa do equipamento (no caso, “admin123”).Ao entrar em modo administrador, um menu é mostrado: *** Modo Administrador: Entre com ****

           1.Para redefinir a password do usuário 1.
           2.Para redefinir a password do usuário 2.
           3.Para configurar uma mensagem para o usuário 1.
           4.Para configurar uma mensagem para o usuário 2.
           5.Para bloquear/desbloquear o usuário 1.
           6.Para bloquear/desbloquear o usuário 2.
           7.Para obter um relatório de tentativas de acesso com erro de senha.
           8.Para sair do modo administrador.

. Como é possível notar pelo menu, é possível personalizar uma mensagem para cada usuário. Desta forma, quando um usuário acessa o sistema, uma mensagem personalizada de boas vindas é mostrada. O administrador também pode bloquear/debloquear o acesso de um usuário.


Obs1: as senhas de usuários nunca poderão ser iguais; Obs2: a opção 7 permite mostrar quantos acessos foram realizados com erro desde que o sistema começou a funcionar. Obs3: após o administrador selecionar uma opção, o sistema voltará ao funcionamento normal em modo usuário.


import java.util.Locale;
import java.util.Scanner;

public class A2T4 {

    static String senha1, msgUsuario1;
    static String senha2, msgUsuario2;
    static Scanner teclado;

    public static void imprimeMenu() {

    }    
    
    public static void modoAdministrador() {
        /* implemente aqui o código associado ao administrador */

    }

    public static void trataUsuario1() {
        /* Implemente aqui o código dedicado ao usuário 1 */
        System.out.println(msgUsuario1);
    }

    public static void trataUsuario2() {
        /* Implemente aqui o código dedicado ao usuário 2 */
        System.out.println(msgUsuario2);
    }

    public static void main(String[] args) {
        teclado = new Scanner(System.in);
        teclado.useLocale(Locale.ENGLISH);
        String senhaLida;


        senha1 = "abc";
        msgUsuario1 = "Alô usuário 1!";
        senha2 = "def";
        msgUsuario2 = "Alô usuário 2!";


        while (true) {
            System.out.println("Entre com uma senha");
            senhaLida = teclado.nextLine();

            if (senhaLida.equals("admin123")) {           
                /* Implemente aqui o código de  modo administrador */
                modoAdministrador();
            } else if (senhaLida.equals(senha1)) { 
                trataUsuario1();;
            } else if (senhaLida.equals(senha2)) {
                /* Implemente aqui o código dedicado ao usuário 2 */
                trataUsuario2();              
            } else {
                System.out.println("Senha não registrada!!!");
            }
        }
    }
}

Exercício 7

Implementar um programa Java que permite desenhar de forma configurável a figura abaixo:

bbbXXXXXX
bbbXXXXX
bbbXXXX
bbbXXX
bbbXX
bbbYY
bbbYYY
bbbYYYY
bbbYYYYY
bbbYYYYYY

Os seguintes parâmetros devem ser configurados (lidos): margem: valor inteiro ÍMPAR de 1 a 9. ; largura da figura: valor inteiro PAR de 6 a 30.

As seguinte exigÊncias são colocadas:

  • um método de entrada de dados deve ser criado com a seguinte assinatura:
  int lerDados(int limInf, int limSup, boolean ehpar);

Este método deve usar um comando while() ou do while() (não é permitido usar loop eterno);

  • um método para desenho da figura. Este método deve invocar outros dois métodos para construir a parte superior e inferior da figura.

Exercício 8

Implemente um método em Java que calcula para um dado inteiro 'n', onde a seguinte função:

NÃO pode usar a biblioteca matemática. Assumir que o usuário não erra e nunca chama a função para

Exercício 9

A seguinte série (de Taylor) permite computar uma aproximação para o valor de :

Implemente um método Java que usa a função implementada anteriormente e que permite calcular os primeiros N termos da série. No programa principal apresente uma tabela com os valores de pi computados para N=10000,20000 e 30000.

Exercício 10

Considere no exercício de controle de acesso que uma senha somente pode começar com letra maiúscula e ter exatamente 6 caracteres. Implemente um método para validar esta condição. O método deve receber como parâmetro a string a ser analisada e deve retornar um valor inteiro que reflete as seguintes condições:

0 - se a string atende a especificação;
1 - se a string não começa com letra maiúscula;
2 - se a string não tem 6 caracteres.
3 - se a string não tem 6 caracteres e não começa com maiúscula.