6  Métodos

Separar decisões, cálculos e efeitos

6.1 Objetivos de aprendizagem

Ao concluir este capítulo, você deverá ser capaz de:

  • identificar parâmetros, retorno e corpo de um método;
  • extrair responsabilidades do método main;
  • diferenciar cálculo de entrada e saída;
  • compreender passagem de argumentos por valor;
  • usar sobrecarga sem criar ambiguidade.

6.2 Contratos pequenos e claros

Dois argumentos entram no método somar e produzem um valor inteiro de retorno.

O contrato de um método transforma argumentos em um resultado.

A assinatura comunica o que um método recebe e devolve:

public static int somar(int primeiro, int segundo) {
    return primeiro + segundo;
}

O nome deve expressar intenção. normalizarComando é mais informativo que processar.

6.3 Refatorando o chatbot

import java.util.Locale;

public class Capitulo05Metodos {
    public static String normalizarComando(String entrada) {
        if (entrada == null) {
            return "";
        }
        return entrada.strip().toLowerCase(Locale.ROOT);
    }

    public static String responder(String entrada) {
        String comando = normalizarComando(entrada);

        return switch (comando) {
            case "oi" -> "Olá!";
            case "ajuda" -> "Comandos: oi, ajuda, dica e sair.";
            case "dica" -> "Um método deve ter uma responsabilidade principal.";
            case "sair" -> "Até logo!";
            case "" -> "Digite uma mensagem.";
            default -> "Não entendi. Digite ajuda.";
        };
    }

    public static boolean deveEncerrar(String entrada) {
        return normalizarComando(entrada).equals("sair");
    }

    public static void main(String[] args) {
        System.out.println(responder("  DICA "));
    }
}

normalizarComando e responder são determinísticos: para a mesma entrada, devolvem o mesmo resultado. Isso facilita testes. O main fica responsável apenas por coordenar a execução e mostrar resultados.

6.4 Escopo e passagem por valor

Uma estudante mostra um método enorme e o JavaBot sugere dividir responsabilidades.

Quadrinho: o método faz-tudo.

Variáveis locais existem somente no bloco em que foram declaradas. Java sempre passa argumentos por valor. Para tipos primitivos, o valor é copiado; para objetos, o valor copiado é a referência. O método pode alterar o objeto apontado por essa referência, mas não substituir a variável original de quem fez a chamada.

public static void incrementar(int numero) {
    numero++;
}

Depois de chamar incrementar(valor), a variável valor do chamador continua inalterada.

6.5 Sobrecarga

Sobrecarga permite métodos com o mesmo nome e listas de parâmetros diferentes:

public static int calcularTotal(int a, int b) {
    return a + b;
}

public static double calcularTotal(double a, double b) {
    return a + b;
}

O tipo de retorno sozinho não diferencia duas sobrecargas.

6.6 Validação e exceções

Um método deve rejeitar valores que violam seu contrato:

public static double calcularMedia(double soma, int quantidade) {
    if (quantidade <= 0) {
        throw new IllegalArgumentException("A quantidade deve ser positiva.");
    }
    return soma / quantidade;
}

A exceção torna a falha explícita. Mais adiante, você decidirá onde capturá-la.

6.7 Evolução do projeto: versão 5

O fluxo do chatbot agora está dividido em três decisões reutilizáveis:

  • normalizar entrada;
  • produzir resposta;
  • decidir se a conversa deve terminar.

O exemplo completo está em examples/src/Capitulo05Metodos.java.

6.8 Prática verificável

  1. Crie ehComandoConhecido(String).
  2. Crie mensagemDeBoasVindas(String nome).
  3. Reescreva o laço do capítulo anterior chamando esses métodos.

Casos de teste para normalizarComando:

Entrada Retorno
" AJUDA " "ajuda"
"" ""
null ""
DicaCritério de domínio

O método main deve ser legível como um roteiro. Se ele contiver todas as regras, ainda há responsabilidades a extrair.