Baixe o app para aproveitar ainda mais
Prévia do material em texto
5/24/10 1 Programação I Cap. 5 - Estruturas Christiano Braga cbraga@ic.uff.br 1 Estruturas • Programas em geral não computam utilizando somente tipos primitivos como os números naturais e texto mas sim com tipos de dados resultantes da composição de outros tipos. • Estruturas representam esta composição e implementam essencialmente a noção de produto cartesiano entre conjuntos. 2 Exemplos de estruturas • Quando você seleciona uma música no seu MP3 player, a entrada dela tem o nome da música, o autor da música, o álbum e talvez um contador no número de vezes que ela foi tocada. • Ou seja, a entrada no catálogo de músicas é o resultado da composição dos tipos texto, três vezes, e um natural. • A representação matemática de uma entrada no catálogo de música pode ser: Entrada = String x String x String x Int, onde o operador ‘x’ representa o produto cartesiano. 3 Estruturas em Java • Nossos programas até o momento eram codificados na forma de classes com funções. • Classes, no entanto, representam uma das formas de definição de tipos em Java. – Outras formas são as interfaces e enumerações que serão vistas mais tarde. • Uma entrada no catálogo de música pode ser representada em Java pela seguinte declaração de classe: class Entrada { String nome ; String autor ; String album ; int contador ; } 4 Criando instâncias de estruturas • Elementos de um tipo, também chamados de instâncias de um tipo, são criados em Java em dois passos: 1. Primeiro declaramos uma variável do cujo o tipo é a classe sendo definida. 2. Instanciamos o tipo através do comando new. • Uma instância da classe Entrada pode ser criada da seguinte forma: Entrada e ; e = new Entrada() ; • Podemos atualizar os campos de uma estrutura como atualizamos uma variável. • O acesso aos campos da estrutura se dá através da chamada “notação de ponto”. • Matematicamente, a notação de ponto representa uma projecão de uma tupla criada através do produto cartesiano entre dois ou mais conjuntos. • Continuando o exemplo: e.nome = “Even flow” ; e.autor = “Pearl Jam” ; e.album = “Ten” ; e.contador = 0 ; 5 Tipos x instâncias • É importante enfatizar a relação entre tipo e instância. • No contexto dos tipos primitivos, o número 1 é uma instância dos números naturais, que podem ser representados em Java pelo tipo int. • No contexto de estruturas, o objeto < “Even flow”, “Pearl Jam”, “Ten”, 0 > é uma instância do tipo Entrada. • Pense em outros exemplos de objetos instâncias do tipo Entrada. • Quantas instâncias do tipo Entrada existem? 6 5/24/10 2 O programa Java até agora... /** * Proposito: Exemplificar a criacao de estruturas como classes. * A classe Entrada representa um estrutura com as informacoes * de uma musica num catalogo de musicas. */ public class Entrada { // nome - nome de uma musica. String nome ; // autor - autor da musica. String autor ; // album - em qual album a musica apareceu a 1a. vez. String album ; // contador - representa o numero de vezes que a musica foi tocada. int contador ; public static void main(String[] args) { Entrada e ; e = new Entrada() ; e.nome = "Even flow" ; e.autor = "Pearl Jam" ; e.album = "Ten" ; e.contador = 0 ; System.out.println("Nome = " + e.nome) ; System.out.println("Autor = " + e.autor) ; System.out.println("Album = " + e.album) ; System.out.println("Contador = " + e.contador) ; } } 7 Funções e procedimentos sobre estruturas • Da mesma forma que definimos funções que recebem tipos primitivos como String ou int podemos escrever funções ou procedimentos que recebem estruturas. • Por exemplo o procedimento toca que incrementa o contador de uma dada Entrada. static void toca(Entrada e){ e.contador = e.contador + 1 ; } 8 Funções e procedimentos sobre estruturas • De maneira similar podemos escrever uma função que cria instâncias de estruturas. • Estas funções podem ter parâmetros assim como as funções definimos até o momento. static Entrada criarEntrada(String nome, String autor, String album, int c) { Entrada e = new Entrada() ; e.nome = nome ; e.autor = autor ; e.album = album ; e.contador = c ; return e ; } 9 O programa Java até agora... de novo! public class Entrada { String nome ; String autor ; String album ; int contador ; static Entrada criarEntrada(String nome, String autor, String album, int c) { Entrada e = new Entrada() ; e.nome = nome ; e.autor = autor ; e.album = album ; e.contador = c ; return e ; } public static void toca(Entrada e) { e.contador = e.contador + 1 ; } public static void main(String[] args) { Entrada e ; e = criarEntrada("Even flow", "Pearl Jam", "Ten", 0) ; System.out.println("Nome = " + e.nome) ; System.out.println("Autor = " + e.autor) ; System.out.println("Album = " + e.album) ; toca(e) ; System.out.println("Contador = " + e.contador) ; } } 10 Construtores e métodos • Java tem uma sintaxe específica para a implementação de procedimentos para a criação de instâncias de classes ao invés de implementarmos procedimentos como o criarEntrada. • Estes procedimentos são chamados de construtores. • O nome de um procedimento construtor leva o mesmo nome da classe a ser instanciada. • Em geral, o construtor inicializa os campos da classe sendo instanciada. 11 Construtor da classe Entrada 12 Entrada(String nome, String autor, String album, int contador) { this.nome = nome ; this.autor = autor ; this.album = album ; this.contador = contador ; } • Quais são as diferenças para o procedimento criarEntrada? 5/24/10 3 Construtor da classe Entrada 1. A assinatura do construtor tem uma sintaxe específica, como dissemos antes. O nome do construtor é o nome da classe sendo instanciada e a declaração do construtor não tem tipo de retorno: está implícito pelo nome do construtor. 2. O construtor não precisa, explicitamente, retornar uma instância da classe. Isso acontece “automaticamente”. 3. Os campos da instância sendo criada podem ser acessados através da variável especial this que referencia a instância sendo criada. 13 O programa Java até agora... outra vez! public class Entrada { String nome ; String autor ; String album ; int contador ; Entrada(String nome, String autor, String album, int contador) { this.nome = nome ; this.autor = autor ; this.album = album ; this.contador = contador ; } public static void toca(Entrada e) { e.contador = e.contador + 1 ; } public static void main(String[] args) { Entrada e = new Entrada("Even flow", "Pearl Jam", "Ten", 0) ; System.out.println("Nome = " + e.nome) ; System.out.println("Autor = " + e.autor) ; System.out.println("Album = " + e.album) ; toca(e) ; System.out.println("Contador = " + e.contador) ; } } 14 Métodos • Métodos são como funções ou procedimentos mas que tem um primeiro parâmetro implícito: a instância de uma classe. • Em outras palavras, um método é uma função ou procedimento que é aplicado a uma instância específica de uma classe. 15 O procedimento toca escrito como um método na classe Entrada class Entrada { //... Todas aquelas declarações... void toca() { this.contador = this.contador + 1 ; } // ... e outras mais... 16 O programa Java – Orientado a objetos! public class Entrada { // nome - nome de uma musica. String nome ; // autor - autor da musica. String autor ; // album - em qual albuma musica apareceu a 1a. vez. String album ; // contador - representa o numero de vezes que a musica foi tocada. int contador ; Entrada(String nome, String autor, String album, int contador) { this.nome = nome ; this.autor = autor ; this.album = album ; this.contador = contador ; } void toca() { this.contador = this.contador + 1 ; } public static void main(String[] args) { Entrada e = new Entrada("Even flow", "Pearl Jam", "Ten",0) ; System.out.println("Nome = " + e.nome) ; System.out.println("Autor = " + e.autor) ; System.out.println("Album = " + e.album) ; e.toca() ; System.out.println("Contador = " + e.contador) ; } } 17 Compare o procedimento toca da versão anterior da classe Entrada com esta versão. Compare também os proce- dimentos main. Que diferenças você encontra? Versões imperativas e OO 18 void toca() { this.contador = this.contador + 1 ; } public static void main(String[] args) { Entrada e = new Entrada("Even flow", "Pearl Jam", "Ten") ; System.out.println("Nome = " + e.nome) ; System.out.println("Autor = " + e.autor) ; System.out.println("Album = " + e.album) ; e.toca() ; System.out.println("Contador = " + e.contador) ; } public static void toca(Entrada e) { e.contador = e.contador + 1 ; } public static void main(String[] args) { Entrada e = new Entrada("Even flow", "Pearl Jam", "Ten") ; System.out.println("Nome = " + e.nome) ; System.out.println("Autor = " + e.autor) ; System.out.println("Album = " + e.album) ; toca(e) ; System.out.println("Contador = " + e.contador) ; } Versão orientada a objetos Versão imperativa 5/24/10 4 Receita para projeto de programas revisitada Fase Objetivos Atividades Análise de dados e projeto Formular definição de dados. Identificar, na descrição do problema, os diferentes tipos de dados que compõem objetos. Adicionar uma definição de estrutura para cada tipo de objeto. Assinatura da função Nomear os métodos. Especificar os tipos de dados de entrada e retorno dos métodos. Descrever o propósito do método e sua assinatura. Nomear os métodos, as classes de entrada de dados, classes de saída de dados, e especificar seu propósito. //nome : in1 in2 ... -> out //computar ... a partir de x1 Exemplos Relacionar entrada e saída de dados através de exemplos. Estudar a descrição de problema procurando por exemplos. Pensar sobre os exemplos. Validar os resultados, se possível. Produzir novos exemplos. Template Produzir um template de função. Para os parâmetros que são estruturas, produzir comentários com expressões representando as projeções apropriadas. Se o método for condicional, produzir comentários com todos os casos a serem cobertos. Declaração Escrever a declaração da função. Escrever um método Java. Testes Descobrir erros. Aplicar os métodos aos valores identificados nos exemplos. Verificar se os resultados são os esperados. 19 Exercício: pontos num plano • Implemente uma classe Point que representa um ponto num plano. • Implemente um método distanceToOrigin que calcule a distância de um dado ponto a origem do plano. 20 Exercício: desenhando num canvas • Um canvas é um objeto sobre o qual podemos desenhar. • Utilize a classe StdDraw para realizar seu trabalho. – A classe StdDraw pode ser obtida do site http:// www.cs.princeton.edu/introcs/stdlib/StdDraw.java. – Sua documentação está disponível em http:// www.cs.princeton.edu/introcs/stdlib/javadoc/StdDraw.java • Alguns dos métodos da classe são os seguintes: 21 Exercício: desenhando num canvas • static void clear() – Limpa a tela. • static void line(double x0, double x1, double y0, double y1) – Desenha uma linha do ponto (x0, y0) ao ponto (x1, y1). • static void filledSquare(double x, double y, double r) – Desenha um quadrado cheio com lado 2r centrado no ponto (x,y). • static void filledCircle(double x, double y, double r) – Desenha um círculo cheio com centro em (x,y) e raio r. • static void circle(double x, double y, double r) – Desenha um circulo com centro em (x, y) e raio r. • void setPenColor() – Define a cor da caneta como preta. 22 Cores • Podemos também mudar a cor da caneta. Existem algumas cores pré-definidas e são do tipo java.awt.Color. – Um rápido comentário sobre a classe Color. Ela “reside” dentro do pacote awt, que por sua vez reside dentro do pacote java. Pacotes são, basicamente, aglomerações de classes. • As cores pré-definidas são: BLACK, BLUE, CYAN, DARK_GRAY, GRAY, GREEN, LIGHT_GRAY, MAGENTA, ORANGE, PINK, RED, WHITE e YELLOW. • Podemos mudar a cor da caneta para qualquer uma destas cores utilizando a função: – static void setPenColor(java.awt.Color c) 23 Temporização • Podemos atrasar a apresentação dos elementos gráficos através da função – static void show(int t) • Esta função faz com que o programa atrase t milisegundos a apresentação das figuras geométricas desenhadas após sua chamada. • É necessário invocar a função – static void show() após desenhar as figuras. 24 5/24/10 5 Exercício: Sinal de trânsito 1. Implemente uma função que desenhe um sinal de trânsito no canvas. Isto é, um retângulo com três círculos dentro. 2. Implemente uma função que faça o sinal ficar vermelho. 3. Implemente uma função que faça o sinal ficar amarelo. 4. Implemente uma função que faça o sinal ficar verde. 5. Implemente um procedimento main que: a. mude a cor do sinal para vermelho, b. apague todo o sinal, c. mude a cor do sinal para amarelo, d. apague todo o sinal, e. mude a cor do sinal para verde e f. apague todo o sinal. 25 Inclusão de tipos • Já vimos os seguintes tipos básicos (ou pré- definidos) que representam números: – int – representando os números inteiros. – double – representando os números reais. • Estes tipos, entendidos como conjuntos, satisfazem a seguinte expressão de inclusão: 26 € int ⊆ double Coerção entre tipos • Uma função, método ou procedimento, pode ser chamada com um valor (parâmetro real) de um tipo menor do que o tipo do parâmetro na sua declaração (parâmetro formal), isto é, de um tipo contido no tipo do parâmetro formal. 27 double area (double r) { return 3.14 * r * r; } public static void main(String[] args) { area(2) ; } Coerção • E o contrário? Podemos declarar int f(int p) e invocar f(3.14)? • Em alguns casos esta perda de precisão é intencional e desejada. Devemos então escrever, por exemplo, f((int) d), com d, por exemplo, uma variável do tipo double. 28 Inclusão de tipos II • Tipos definidos pelo usuário podem ter uma relação de inclusão da mesma maneira que os tipos primitivos. • Consideremos o exemplo de desenho num canvas. • Podemos pensar em tipos representando cada uma das formas geométricas que utilizamos. • Mais ainda, podemos pensar num tipo que contenha todas as nossas formas geométricas. 29 Formas geométricas 30 GeometricShape Square Circle Line € Square⊆ GeometricShape Circle⊆ GeometricShape Line ⊆ GeometricShape 5/24/10 6 Herança • A relação de inclusão entre tipos definidos como classe se chama herança na terminologia de programação orientada a objetos. • No exemplo das formas geométricas dizemos que a classe Square herda da classe GeometricShape. • Objetos instâncias da classe Square são também instâncias de GeometricShape. 31 A classe GeometricShape • A classe GeometricShape pode ser declarada da seguinte forma: 32 import java.awt.Color; abstract class GeometricShape { protected Color color ; GeometricShape(Color c) { color = c ; } abstract void draw() ; abstract void erase() ; }Classes abstratas • Em Java é possível declarar classes abstratas. • O significado de uma classe abstrata c é o de um tipo t que somente tem como instâncias elementos que sejam instâncias de subtipos de t, isto é, classes que herdem da classe c. • No exemplo das formas geométricas, a classe GeometricShape não terá instâncias. • Ao declararmos uma variável do tipo GeometricShape ela somente poderá ficar associada a objetos instâncias de classes que herdem de GeometricShape. 33 Classes herdeiras de GeometricShape • As classes Rectangle, Circle e Line herdam de GeometricShape. São chamadas classes herdeiras ou filhas de GeometricShape. • Cada uma delas implementa os métodos draw e erase a sua maneira. 34 Escopo dos atributos de uma classe • Note que os atributos canvas e color da classe GeometricShape foram declarados com o modificador protected. Isso significa que estes atributos podem ser utilizados por instâncias das classes herdeiras. • Se o modificador utilizado tivesse sido private, isso não seria possível. Somente instâncias de GeometricShape poderiam acessar estes atributos. • Se o modificador fosse public objetos de outras classes poderiam acessar estes atributos. 35 A classe Square import java.awt.Color ; class Square extends GeometricShape { private Point origin ; private double side ; Square(Color c, Point o, double s) { super(c) ; origin = o ; side = s ; } void draw() { Color c = StdDraw.getPenColor() ; StdDraw.setPenColor(color) ; StdDraw.filledSquare(origin.x, origin.y, side) ; StdDraw.setPenColor(c) ; } void erase() { Color c = StdDraw.getPenColor() ; StdDraw.setPenColor(StdDraw.WHITE) ; StdDraw.filledSquare(origin.x, origin.y, side) ; StdDraw.setPenColor(c) ; } } 36 5/24/10 7 Classes Circle e Line • Como fica a declaração destas classes? 37 Um exemplo de procedimento main 38 import java.awt.* ; class Example { public static void main(String[] args) { Square r = new Square(StdDraw.BLUE, new Point(.5,.5), 0.15) ; r.draw() ; StdDraw.show(500) ; r.erase() ; StdDraw.show() ; } } Receita de projeto de programa revisitada 39 Fase Objetivos Atividades Análise de dados e projeto Formular definição de dados. Identificar, na descrição do problema, os diferentes tipos de dados que compõem objetos. Adicionar uma definição de estrutura (classes) para cada tipo de objeto. Identificar diferentes tipos de classes de dados. Assinatura da função Nomear os métodos. Especificar os tipos de dados de entrada e retorno dos métodos. Descrever o propósito do método e sua assinatura. Nomear os métodos, as classes de entrada de dados, classes de saída de dados, e especificar seu propósito. //nome : in1 in2 ... -> out //computar ... a partir de x1 Exemplos Relacionar entrada e saída de dados através de exemplos. Estudar a descrição de problema procurando por exemplos. Pensar sobre os exemplos. Validar os resultados, se possível. Produzir novos exemplos. Template Produzir um template de função. Definir métodos comuns a classes de dados. Para os parâmetros que são estruturas, produzir comentários com expressões representando as projeções apropriadas. Se o método for condicional, produzir comentários com todos os casos a serem cobertos. Declaração Escrever a declaração da função. Escrever um método Java. Implementar os diferentes comportamentos para cada método. Testes Descobrir erros. Aplicar os métodos aos valores identificados nos exemplos. Verificar se os resultados são os esperados. Exercício: Sinal de trânsito revisitado • Refaça o exercício do sinal de trânsito utilizando as classes GeometricShape, Square, Circle e Line. 40
Compartilhar