Mudanças entre as edições de "Pensamento Computacional - Métodos no Java"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
Linha 205: Linha 205:
 
No programa principal, mostre  em uma única instrução como seria a computação da soma de dois fatoriais: <math>somaFatorial = N! + M! </math>
 
No programa principal, mostre  em uma única instrução como seria a computação da soma de dois fatoriais: <math>somaFatorial = N! + M! </math>
  
=Variáveis locais=
+
=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.
 
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.
Linha 214: Linha 214:
 
É 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.
 
É 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.
+
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==
 
==Exercício==
Linha 246: Linha 252:
 
     static String senha1, msgUsuario1;
 
     static String senha1, msgUsuario1;
 
     static String senha2, msgUsuario2;
 
     static String senha2, msgUsuario2;
    static String senhaLida;
 
 
     static Scanner teclado;
 
     static Scanner teclado;
  
Linha 271: Linha 276:
 
         teclado = new Scanner(System.in);
 
         teclado = new Scanner(System.in);
 
         teclado.useLocale(Locale.ENGLISH);
 
         teclado.useLocale(Locale.ENGLISH);
 +
        String senhaLida;
  
  

Edição das 20h11min de 10 de novembro de 2023

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.

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

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!!!");
            }
        }
    }
}