Aula 5 Métodos, Parâmetros, Argumentos e Contratos Na aula passada … Ciclos: while (condição) {passo; progresso;} for (init; condição; progresso) {passo;} do {passo; progresso;} while (condição); Matrizes: int[] matriz_de_inteiros = new int[100]; matriz_de_inteiros[99] = 10; int x = matriz_de_inteiros[99]; String: 2 String frase = “Uma frase”; String frase = new String(“Uma frase”); char primeiro = frase.charAt(0); char último = frase.charAt(frase.length() – 1)); Introdução à Programação 2007/2008 Modularização em Java Métodos (ou Rotinas)* Funções Conjunto de instruções, com interface bem definida, que efectua um dado cálculo • Devolvem explicitamente um resultado ao exterior Procedimentos Conjunto de instruções, com interface bem definida, que faz qualquer coisa • Não devolvem explicitamente um resultado ao exterior Nota * : designam-se muitas vezes por Sub-programas ou Rotinas; correspondem a operações (conjuntos de instruções) que um programa (ou Classe) executa, quando dele se pretende uma dado comportamento 3 Introdução à Programação 2007/2008 Sintaxe (declaração) Classe? static? Falaremos disto mais tarde Funções de classe public static tipo nome(parâmetros) { instruções; Declaração / cabeçalho return variável; Corpo } Tipo e nome de cada parâmetro (separados por virgulas), ex: (int x, char a, String s, double[][] m) Variáveis que só existem dentro do método (var. locais) 4 Introdução à Programação 2007/2008 Sintaxe (declaração) Procedimentos de classe public static void nome(parâmetros) { instruções; } Declaração / cabeçalho Corpo Tipo e nome de cada parâmetro (separados por virgulas), ex: (int x, char a, String s, double[][] m) Variáveis que só existem dentro do método (var. locais) 5 Introdução à Programação 2007/2008 Sintaxe (utilização) parâmetros do método Estando declarada a função de classe public static tipo nome(tipo1 par1, …) {…} Usa-se do seguinte modo : tipo var_retorno = nome(arg1, arg2, …) ( a sua chamada integra-se numa instrução para o valor de retorno poder ser utilizado ) Estando declarado o procedimento de classe public static void nome(tipo1 par1,…) {…} Usa-se do seguinte modo: nome(arg1, arg2, …) ( basta saber o nome do procedimento, para que serve e que eventuais dados necessita ) 6 Introdução à Programação 2007/2008 Passagem de argumentos Parâmetros (do método) são sinónimos dos argumentos respectivos (com que é chamado o método) Em Java não há indicação explícita de passagem por referência! Argumentos são sempre passados por valor (ainda que o valor seja uma referência) 7 Tipos primitivos: parâmetro é uma cópia do valor do argumento Outros tipos: parâmetro é uma cópia da referência (i.e. aponta para os mesmos dados que o argumento) Introdução à Programação 2007/2008 Tamanho dos métodos Ideal 8 até 10 linhas Em casos extremos (sintético, estruturado, simples e claro) Normal 1 a 5 linhas até 60 linhas Nunca mais de 60 linhas! Introdução à Programação 2007/2008 Construindo uma função Uma função que procura, numa lista (matriz) de palavras (String), uma palavra começada por uma determinada letra e devolve a primeira encontrada nessas condições, ou null se não encontrar: O que será devolvido? Como se chama a função? Quais os dados (parâmetros) que precisa? Qual o algoritmo? 9 Introdução à Programação 2007/2008 Construindo uma função Uma função que procura numa matriz uma palavra começada por uma letra O que é devolvido? uma palavra Qual o nome da função? procuraPalavra (sem espaços!) Quais os dados que precisa? uma matriz de palavras e uma letra (são dois parâmetros) Em Java: public static String procuraPalavra(String[] lista_de_palavras, char letra) 10 Introdução à Programação 2007/2008 Construindo uma função Uma função que procura numa matriz uma palavra começada por uma letra public static String procuraPalavra(String[] lista_de_palavras, char letra) { // começa a procurar no início da lista // enquanto não chegar ao fim e não encontrar palavra começada pela letra pedida, fazer: // … continua a procurar no resto da lista (progresso) // se encontrou palavra então devolve-a // senão devolve null } 11 Introdução à Programação 2007/2008 Construindo uma função public static String procuraPalavra(String[] lista_de_palavras, char letra) { int i = 0; // começa no início da lista; enquanto não chegar ao fim da lista // e não encontrar palavra começada pela letra pedida, fazer: while (i != lista_de_palavras.length } ++i; && letra != lista_de_palavras[i].charAt(0)) { // continua a procurar no resto da lista if (i != lista_de_palavras.length) return lista_de_palavras[i]; // se encontrou palavra então … // … devolve-a return null; // senão devolve null } Porque não está aqui o else ? 12 Introdução à Programação 2007/2008 Exemplo de um procedimento Um procedimento que pergunta uma letra ao utilizador e escreve no ecrã uma palavra (existente numa matriz) começada por essa letra ou indica ao utilizador que não encontrou O que é devolvido? Como se chama o procedimento? Quais os dados que precisa? Qual o algoritmo? 13 Introdução à Programação 2007/2008 Exemplo de um procedimento Um procedimento que pergunta uma letra ao utilizador e escreve no ecrã uma palavra começada por essa letra O que é devolvido? NADA! (escrever no ecrã NÃO É o mesmo que devolver) Como se chama o procedimento? escrevePalavra (ou escrevePalavraComeçadaPor) Quais os dados que precisa? Uma lista de palavras (solicitada ao utilizador dentro do procedimento) Em Java: public static void escrevePalavra(String[] lista_de_palavras) 14 Introdução à Programação 2007/2008 Exemplo de um procedimento Procedimento que pergunta uma letra ao utilizador e escreve no ecrã uma palavra começada por essa letra public static void escrevePalavra(String[] lista_de_palavras) { // pede ao utilizador para inserir uma letra // Lê a letra // procura palavra começada por: letra em lista_de_palavras // se encontrou // … mostra palavra ao utilizador // senão // … mostra ao utilizador mensagem a indicar que não encontrou } 15 Introdução à Programação 2007/2008 Exemplo de um procedimento Procedimento que pergunta uma letra ao utilizador e escreve no ecrã uma palavra começada por essa letra public static void escrevePalavra(String[] lista_de_palavras) { System.out.println(“Introduza uma letra e <enter>: ”); Scanner teclado = new Scanner (System.in); String s = teclado.next(); // Lê a letra char letra = s.charAt(0); // procura palavra começada por: letra String palavra = procuraPalavra (lista_de_palavras, letra); if (palavra != null) { // se encontrou … mostra palavra ao utilizador System.out.println(“Palavra encontrada: ” + palavra); } else { // senão … mostra ao utilizador … que não encontrou System.out.println(“Palavra não encontrada”); } Este else é necessário? } 16 Introdução à Programação 2007/2008 Utilização do procedimento public class CodificadorDeLetra { // declaração da função e procedimento public static void main(String[] argumentos) { String[] palavras = {“Alfa”, “Bravo”, “Charlie”, “Dado”, “Era”, \\ …, “Wolkswagen”,”Zebra”}; escrevePalavra(palavras); } } 17 Introdução à Programação 2007/2008 Fluxo de controlo Início do programa 1. Chamada de main() (sempre) 2. Chamada de escrevePalavra() 3. Chamada de procuraPalavra() Programa CodificadorDeLetra escrevePalavra() 5 • 3 4 4. Devolução de procuraPalavra() • procuraPalavra() 1 2 main() escrevePalavra() ainda em execução! devolve a palavra encontrada e volta a executar escrevePalavra() no ponto onde foi suspenso 5. Retorno de escrevePalavra() • Não devolve nada, é um procedimento Fim do programa (Duvida? faça o traçado/debug e verifique) 18 Introdução à Programação 2007/2008 Outro exemplo: Somador de fracções public class SomadorDeFracções { /** ... */ public static int mdc (final int m, final int n) { ... } /** ... */ public static void escreveFracção (final int n, final int d) { ... } public static void main(String[] argumentos) { ... } } 19 Introdução à Programação 2007/2008 Papeis do programador Programador assume papeis distintos: Produtor • Desenvolve mecanismo do módulo • Preocupa-se com: • o que faz • como se vai usar • como funciona Consumidor • Integra cada módulo num sistema mais complexo • Preocupa-se com: • o que faz • como se usa (que argumentos precisa) 20 Introdução à Programação 2007/2008 Contrato (programação por…) Entre produtor e consumidor Produtor: Indica como se usa Produtor: Garante resultados … …se consumidor respeitar condições de utilização 21 Introdução à Programação 2007/2008 Contrato (programação por…) Dito de outro modo: Permite indicar quais as funcionalidades que são oferecidas ao “exterior” Indica que tipo de informação precisa para executar a função Indica qual deverá ser o comportamento esperado Comportamento descrito com a máxima exactidão possível 22 Introdução à Programação 2007/2008 Contrato (programação por…) Cada método deve indicar o seu contrato Cada contrato contém (pelo menos) Descrição sumária do funcionamento Restrições aos argumentos a fornecer • Pré-condições Resultado preciso da execução • Condição Objectivo • Para funções, se possível: nome=<expressão c/ param.> • Se for procedimento, mais informalmente dizer o que faz 23 Introdução à Programação 2007/2008 Máximo divisor comum (VIII) /** Devolve o máximo divisor comum dos inteiros positivos passados como argumento. @pre 0 < m e 0 < n. @post o valor r devolvido é o mdc de m e n. */ public static int mdc(final int m, final int n) { int r; Documentação: o que faz? quais os valores possíveis para os argumentos? if(m < n) r = m; else Cabeçalho: como se usa r = n; while(m % r != 0 || n % r != 0) --r; Corpo: como funciona ? return r; (só o produtor é que se preocupa com esta parte) } 24 Introdução à Programação 2007/2008 Máximo divisor comum (IX) /** Devolve o máximo divisor comum dos inteiros positivos passados como argumentos. @pre 0 < m e 0 < n. @post o valor r devolvido é o mdc de m e n. */ public static int mdc(final int m, final int n) { assert 0 < m; assert 0 < n; Instruções de asserção (afirmação) … assert 0 < r; assert m % r == 0; assert n % r == 0; return r; } 25 Introdução à Programação 2007/2008 Máximo divisor comum (com tratamento de Excepções) /** Devolve o máximo divisor comum dos inteiros positivos passados como argumentos. @pre 0 < m e 0 < n Atenção às pré-condicões! @post return r (é o mdc de m e n) */ public static int mdc (final int m, final int n) { if (m <= 0 || n <= 0) throw new IllegalArgumentException ("Pelo menos um dos argumentos é errado!"); … verificar a validade dos argumentos antes de usar! return r; } 26 Introdução à Programação 2007/2008 Outro exemplo: Busca estranha... (com tratamento de Excepções) /** Devolve o caractere que tem o índice x numa dada String (o inteiro x e a String s passados como argumentos) Atenção às pré-condicões! @pre s != null e 0 <= x < s.length() @post return caractere com índice x em s */ // ... public static char charAtVerificado (String s, int x){ if (s == null || x < 0 || x >= s.length()) throw new IllegalArgumentException("Wrong Argument"); return s.charAt(x); } } verificar a validade dos argumentos antes de usar! 27 Introdução à Programação 2007/2008 Especificação de contrato No cabeçalho de rotinas Etiquetas @pre, @post, etc. Forçar a existência de pré e pós-condições – e recorrer a asserções – dá origem a programas optimizados, e minimiza os erros de programação. No código Java Instruções assert Uma asserção é uma instrução que permite testar determinados pontos-chave do programa. As asserções permitem confirmar se o funcionamento do programa corresponde ao que dele esperamos/pretendemos. 28 Introdução à Programação 2007/2008 Especificação de contrato Pré-condições e condições objectivo 29 Possível especificá-las: Ao nível de métodos Ao nível de instruções mais elementares Introdução à Programação 2007/2008 Exemplo: absolutoDe() /** Devolve o valor absoluto do parâmetro. O que faz @pre ?. @post ?. */ public static int absolutoDe (final int valor) { ... } Como funciona Como se usa 30 Introdução à Programação 2007/2008 absolutoDe(): pré-condição /** Devolve o valor absoluto do argumento. @pre V. // Todos os valores do parâmetro são válidos @post ?. */ public static int absolutoDe(final int valor) { ... } 31 Introdução à Programação 2007/2008 absolutoDe(): condição-objectivo /** Devolve o valor absoluto do argumento. @pre V. @post 0 ≤ absolutoDe. */ public static int absolutoDe (final int valor) { ... } É suficiente? Não há relação entre o valor devolvido e valor! 32 Introdução à Programação 2007/2008 absolutoDe(): condição-objectivo /** Devolve o valor absoluto do argumento. @pre V. @post 0 ≤ absolutoDe. */ public static int absolutoDe (final int valor) { return 5; } Errado! Mas, ... A condição objectivo (C.O.) verifica-se! Há muitas C.O. que são válidas, mas umas são melhores que outras (as mais restritivas) 33 Introdução à Programação 2007/2008 absolutoDe(): Cond.-Objectivo /** Devolve o valor absoluto do argumento. @pre V. @post 0 ≤ absolutoDe e (absolutoDe = valor ou absolutoDe = -valor). */ public static int absolutoDe (final int valor) { ... } 34 Introdução à Programação 2007/2008 absolutoDe() /** Devolve o valor absoluto do argumento. @pre V. @post 0 ≤ absolutoDe e (absolutoDe = valor ou absolutoDe = -valor). */ public static int absolutoDe (final int valor) { int absoluto; ... return absoluto; } 35 Introdução à Programação 2007/2008 absolutoDe() /** Devolve o valor absoluto do argumento. @pre V. @post 0 ≤ absolutoDe e (absolutoDe = valor ou absolutoDe = -valor). */ public static int absolutoDe(final int valor) { // V int absoluto; Asserções: afirmações acerca do estado do programa ... // 0 ≤ absoluto e // (absoluto = valor ou absoluto = -valor) return absoluto; } 36 Introdução à Programação 2007/2008 absolutoDe() /** Devolve o valor absoluto do argumento. @pre V. @post 0 ≤ absolutoDe e (absolutoDe = valor ou absolutoDe = -valor). */ public static int absolutoDe(final int valor) { assert true; Instruções de Asserções: afirmações asserção: acerca do estado verificação explícita dode programa asserções. // V int absoluto; Para usar no Eclipse é necessário a flag de execução – ea. (Run/Run/(X)=Arguments/VM arguments): -ea ... // 0 ≤ absoluto e // (absoluto = valor ou absoluto = -valor) assert 0 <= absoluto; assert absoluto == valor || absoluto == -valor; return absoluto; } 37 Introdução à Programação 2007/2008 absolutoDe() /** Devolve o valor absoluto do argumento. @pre V. @post 0 ≤ absolutoDe e (absolutoDe = valor ou absolutoDe = -valor). */ public static int absolutoDe(final int valor) { Instruções de Asserções: afirmações asserção: acerca do estado verificação explícita dode programa asserções. int absoluto; ... // 0 ≤ absoluto e // (absoluto = valor ou absoluto = -valor) Para usar no Eclipse é necessário a flag de execução – ea. (Run/Run/(X)=Arguments/VM arguments): -ea assert 0 <= absoluto; assert absoluto == valor || absoluto == -valor; return absoluto; } 38 Introdução à Programação 2007/2008 absolutoDe() Instruções que resolvem o problema: absoluto = valor; absoluto = -valor; 39 Introdução à Programação 2007/2008 absolutoDe(): PC1 // PC1: 0 ≤ -valor e // (-valor = valor ou -valor = -valor), ou seja, // PC1: valor ≤ 0 e (-valor = valor ou V), ou seja, // PC1: valor ≤ 0 e V, ou seja, // PC1: valor ≤ 0 if (valor <= 0) absoluto = -valor; // 0 ≤ absoluto e // (absoluto = valor ou absoluto = -valor) 40 Introdução à Programação 2007/2008 absolutoDe(): PC2 // PC2: 0 ≤ valor e // (valor = valor ou valor = -valor), ou seja, // PC2: 0 ≤ valor e (V ou valor = -valor), ou seja, // PC2: 0 ≤ valor e V, ou seja, // PC2: 0 ≤ valor if (valor >= 0) absoluto = valor; // 0 ≤ absoluto e // (absoluto = valor ou absoluto = -valor) 41 Introdução à Programação 2007/2008 absolutoDe() /** Devolve o valor absoluto do argumento. @pre V. @post 0 ≤ absolutoDe e (absolutoDe = valor ou absolutoDe = -valor). */ public static int absolutoDe(final int valor) { assert true; // V int absoluto; if (valor < 0) absoluto = -valor; else absoluto = valor; // 0 ≤ absoluto e (absoluto = valor ou absoluto = -valor) assert 0 <= absoluto; assert absoluto == valor || absoluto == -valor; return absoluto; } 42 Introdução à Programação 2007/2008 A reter... Métodos (ou Rotinas) Servem para agrupar instruções associadas. Executam um cálculo ou procedimento bem definido Têm parâmetros Funções devolvem um valor Procedimentos não devolvem nenhum valor, apenas realizam acções Passagem de argumentos • Tipos primitivos: são cópias, o argumento original não pode ser alterado • Outros: são referências: o argumento original pode ser alterado Programação por contrato • Se o utilizador cumprir as pré-condições (restrições ao valor dos argumentos) o programador da função/instrução garante as pós-condições (restrições ao resultado da rotina) • Pré-condições devem ser sempre verificadas (usando assert ou outros métodos … de que falaremos em breve) 43 Introdução à Programação 2007/2008 A ler... Capítulo 6: Y. Daniel Liang, "Introduction to Java Programming", 5ª Edição, Prentice-Hall, 2005. ISBN: 0-13-185721 - 5 44 Introdução à Programação 2007/2008 Aula 5: Sumário Modularização, abstracção e encapsulamento. Métodos como unidades atómicas de modularização. Sintaxe da definição de métodos: cabeçalho vs. corpo. Comprimento típico de métodos. Interface e implementação. Parâmetros e argumentos. Instrução return. Retorno e devolução. Procedimentos: não há devolução (tipo de devolução void). Invocação de métodos. Parâmetros como instâncias locais. Passagem de argumentos. Contratos e Asserções. 45 Introdução à Programação 2007/2008