Baixe o app para aproveitar ainda mais
Prévia do material em texto
Autor: Prof. José Cassiano Grassi Gunji Colaboradores: Prof. Angel Antonio Gonzalez Martinez Prof. José Carlos Morilla Tópicos Especiais de Programação Orientada a Objetos Professor conteudista: José Cassiano Grassi Gunji Mestre em Tecnologia da Informação Aplicada pelo Centro Estadual de Educação Tecnológica Paula Souza e bacharel em Sistemas de Informação pela Universidade Presbiteriana Mackenzie. Atua como docente em cursos de graduação em Tecnologia da Informação em disciplinas de programação orientada a objetos em diversas linguagens, análise de sistemas, lógica de programação, entre outras. © Todos os direitos reservados. Nenhuma parte desta obra pode ser reproduzida ou transmitida por qualquer forma e/ou quaisquer meios (eletrônico, incluindo fotocópia e gravação) ou arquivada em qualquer sistema ou banco de dados sem permissão escrita da Universidade Paulista. Dados Internacionais de Catalogação na Publicação (CIP) G975t Gunji, José Cassiano Grassi. Tópicos Especiais de Programação Orientada a Objetos / José Cassiano Grassi Gunji. – São Paulo: Editora Sol, 2020. 152 p., il. Nota: este volume está publicado nos Cadernos de Estudos e Pesquisas da UNIP, Série Didática, ISSN 1517-9230. 1. Java. 2. Interfaces. 3. Android. I. Título. CDU 681.3.062 U508.94 – 20 Prof. Dr. João Carlos Di Genio Reitor Prof. Fábio Romeu de Carvalho Vice-Reitor de Planejamento, Administração e Finanças Profa. Melânia Dalla Torre Vice-Reitora de Unidades Universitárias Profa. Dra. Marília Ancona-Lopez Vice-Reitora de Pós-Graduação e Pesquisa Profa. Dra. Marília Ancona-Lopez Vice-Reitora de Graduação Unip Interativa – EaD Profa. Elisabete Brihy Prof. Marcello Vannini Prof. Dr. Luiz Felipe Scabar Prof. Ivan Daliberto Frugoli Material Didático – EaD Comissão editorial: Dra. Angélica L. Carlini (UNIP) Dr. Ivan Dias da Motta (CESUMAR) Dra. Kátia Mosorov Alonso (UFMT) Apoio: Profa. Cláudia Regina Baptista – EaD Profa. Deise Alcantara Carreiro – Comissão de Qualificação e Avaliação de Cursos Projeto gráfico: Prof. Alexandre Ponzetto Revisão: Elaine Pires Vitor Andrade Sumário Tópicos Especiais de Programação Orientada a Objetos APRESENTAÇÃO ......................................................................................................................................................7 INTRODUÇÃO ...........................................................................................................................................................7 Unidade I 1 INTRODUÇÃO AO JAVA ....................................................................................................................................9 1.1 Um breve histórico .............................................................................................................................. 10 1.2 Arquitetura de um programa em Java ........................................................................................ 11 1.3 Características da linguagem Java ................................................................................................ 12 1.4 O que é necessário para programar em Java ............................................................................ 13 1.4.1 Instalando o JDK Java SE ..................................................................................................................... 16 1.4.2 Instalando o Eclipse ............................................................................................................................... 16 2 A LINGUAGEM JAVA ...................................................................................................................................... 17 2.1 Entrada e saída de dados usando JOptionPane ....................................................................... 25 2.2 Recomendações de estilo .................................................................................................................. 30 2.3 Tipos primitivos ..................................................................................................................................... 31 2.4 Conversão de tipos .............................................................................................................................. 32 2.5 Classes wrapper (invólucro) ............................................................................................................. 35 2.6 Introdução a classes e objetos ........................................................................................................ 38 2.7 Instruções de controle ........................................................................................................................ 41 2.8 Arrays ....................................................................................................................................................... 48 2.9 Coleções ................................................................................................................................................... 49 2.10 Tratamento de exceções .................................................................................................................. 51 Unidade II 3 PROGRAMAÇÃO ORIENTADA A OBJETOS .............................................................................................. 59 3.1 Sobrecarga .............................................................................................................................................. 59 3.2 Herança .................................................................................................................................................... 61 3.3 Sobrescrita ............................................................................................................................................... 63 3.4 Polimorfismo .......................................................................................................................................... 64 3.5 Modificadores de acesso ................................................................................................................... 66 3.6 Escopo ....................................................................................................................................................... 67 3.7 Classes abstratas e interfaces .......................................................................................................... 69 4 INTERFACES GRÁFICAS ................................................................................................................................. 74 Unidade III 5 INTRODUÇÃO AO ANDROID ........................................................................................................................ 88 5.1 Arquitetura Android ............................................................................................................................ 89 6 INSTALANDO E UTILIZANDO O ANDROID STUDIO ............................................................................. 90 6.1 Aplicativo “Olá mundo!” .................................................................................................................... 92 6.2 Criação e configuração de um emulador Android ...............................................................101 Unidade IV 7 CALCULADORA DE GORJETAS ..................................................................................................................112 7.1 Layout do aplicativo Calculadora de Gorjetas ........................................................................112 8 CODIFICAÇÃO DO APLICATIVO CALCULADORA DE GORJETA ......................................................132 7 APRESENTAÇÃO Este livro-texto tem como finalidade apresentar um roteiro de estudos para preparar o(a) aluno(a) para desenvolver programas de computador utilizando a tecnologia Java. Todo o conteúdo foi desenvolvido de maneira a permitir que o(a) estudante construa seu conhecimento da tecnologia Java demaneira gradativa. Por isso, para entender as últimas partes do deste material, o(a) aluno(a) deve ter passado por todas as partes anteriores, de modo a acumular conhecimento suficiente para compreender os assuntos desenvolvidos. Não é necessário conhecimento anterior de Java. Entretanto, assume-se que o(a) estudante já esteja familiarizado(a) com os conhecimentos de lógica de programação, assim como de análise de sistemas orientados a objetos. Inicialmente, veremos os conceitos relacionados à tecnologia de programação Java e como essa tecnologia se situa com relação às demais tecnologias em uso hoje. Um pouco da história do desenvolvimento do Java também será apresentado. Na sequência, abordaremos de maneira prática a programação usando a linguagem Java e faremos breves revisões sobre os conceitos da lógica de programação e orientação a objetos aplicados ao Java. Também serão apresentados os recursos do Java para o desenvolvimento de interfaces gráficas com o usuário. Serão apresentados os conceitos relacionados ao ambiente de programação para dispositivos móveis que utilizam o sistema operacional Android e discutiremos os principais aspectos necessários para desenvolver e publicar um aplicativo na loja de aplicativos para Android do Google. INTRODUÇÃO O conhecimento tecnológico dos homens propiciou a criação de diversos mecanismos capazes de realizar tarefas. Há séculos existem aparelhos mecânicos capazes de realizar tarefas dos mais diversos níveis de complexidade. Por exemplo, existiram teares capazes de tecer padrões complexos em tecidos de maneira automática e máquinas capazes de realizar cálculos matemáticos e até mesmo codificar e decodificar mensagens de rádio. A tecnologia desses mecanismos podia ser mecânica, elétrica e, mais recentemente, eletrônica. Algo que esses dispositivos tinham em comum era algum método pelo qual eles poderiam ser programados. Com o desenvolvimento da tecnologia e o surgimento dos computadores digitais, foram desenvolvidas linguagens de programação que esses computadores poderiam interpretar diretamente: as linguagens de máquina. Entretanto, linguagens de máquina são de difícil entendimento para pessoas, e, por isso, logo começaram a ser desenvolvidas linguagens de alto nível. Uma linguagem de alto nível é um código com o qual se pode expressar algoritmos usando um vocabulário e uma sintaxe semelhante ao vocabulário e à sintaxe da linguagem humana, quase sempre em inglês. Esse código escrito em linguagem de alto nível pode ser então traduzido (compilado) para a linguagem de máquina do computador no qual ele será executado. 8 É nesse contexto que surge a linguagem de programação Java. Seus desenvolvedores estipularam uma meta arrojada: criar uma linguagem de programação multiplataforma. Isso significa que um código de computador escrito em Java, depois de compilado, poderia ser executado por qualquer computador, executando qualquer sistema operacional que oferecesse suporte ao Java sem necessidade de recompilar o código-fonte. Como o Java realiza essa tarefa é o que veremos neste livro-texto, assim como aprenderemos a desenvolver aplicativos usando Java tanto para computadores desktop quanto para dispositivos móveis que executem o sistema operacional Android. 9 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Unidade I 1 INTRODUÇÃO AO JAVA Os computadores modernos, seja qual for sua arquitetura ou fabricante, apenas conseguem executar programas escritos em sua própria linguagem de máquina. Uma linguagem de máquina é uma sequência de números escritos na base 16, também conhecida como números hexadecimais. Um trecho de um programa em linguagem de máquina apresenta a aparência da figura a seguir: CD 20 FF 9F 00 9A F0 FE-1D F0 4F 03 F0 07 8A 03 F0 07 17 03 F0 07 DF 07-01 01 01 00 02 FF FF FF FF FF FF FF FF FF FF FF-FF FF FF FF BD 0D 4C 01 D0 0C 14 00 18 00 3D 0E-FF FF FF FF 00 00 00 00 05 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20 20 20 20 20 20 20 20 20-00 00 00 00 00 20 20 20 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 00 0D 76 2E 65 78 65 0D-44 4F 57 53 5C 73 79 73 74 65 6D 33 32 5C 64 6F-73 78 0D 0D 64 61 20 72 65 64 65 20 28 63 61 72-72 65 67 61 72 20 61 6E 74 65 73 20 64 6F 20 64-6F 73 78 2E 65 78 65 29 Figura 1 – Exemplo de um código de computador em hexadecimal Por razões óbvias, é muito difícil para um programador escrever um programa usando linguagem de máquina. Para resolver esse problema, logo começaram a ser desenvolvidas diversas linguagens de computador de alto nível, ou seja, linguagens que permitem que se escrevam algoritmos usando palavras com um vocabulário e uma sintaxe semelhantes ao vocabulário e à sintaxe da linguagem humana, quase todas em língua inglesa. Muitas linguagens nunca atingiram grande aceitação. Outras chegaram a ser usadas com frequência, mas acabaram caindo em desuso. Hoje em dia, há um punhado de linguagens que permanecem bastante populares. Alguns exemplos são o COBOL, o C++ e o C# (DEITEL; DEITEL, 2005; DEITEL; DEITEL, 2010). As linguagens de sucesso sempre apresentam algo que as diferencia das demais, trazendo alguma vantagem com relação às outras. O Java é um desses casos de sucesso. Vejamos como foi a história do desenvolvimento do Java. 10 Unidade I Lembrete Você já deve ter notado que existe uma quantidade enorme de diferentes linguagens de programação, tanto ainda em uso quanto já abandonadas, como Fortran, Smalltalk, Pascal, Delphi, entre tantas outras. Não é tão fácil saber o que faz uma linguagem fazer sucesso e outra ser abandonada. Em geral, uma linguagem que apenas faz o mesmo que outras já fazem acaba sendo superada por outra que inova em algum aspecto. 1.1 Um breve histórico A história da criação do Java é descrita por diversos autores, como Horstmann e Cornell (2010), Deitel e Deitel (2005; 2010), Jorge (2004), entre outros. A Sun Microssystems, em 1991, financiou um projeto de pesquisa corporativa interna com o codinome Green, que resultou no desenvolvimento de uma linguagem baseada em C++, que seu criador, James Gosling, chamou de Oak. Descobriu-se mais tarde que já havia uma linguagem de programação com esse nome. Uma equipe da Sun, em visita a uma cafeteria local que servia café cuja origem era a ilha de Java, na Indonésia, sugeriu esse nome, e ele acabou sendo aceito. O projeto passou por dificuldades e quase foi cancelado. Mas, em 1993, a World Wide Web explodiu em popularidade, e a equipe da Sun viu um grande potencial para utilizar o Java para adicionar conteúdo dinâmico, com interatividade e animações às páginas da Web, o que deu nova vida ao projeto. O Java foi anunciado formalmente em 1995, ganhando muito interesse da comunidade da World Wide Web. Atualmente, o Java é popular no desenvolvimento de software para diversos aplicativos, como aplicativos corporativos de grande porte, aplicativos governamentais, no aprimoramento da funcionalidade de servidores Web, assim como em aplicativos para o consumo popular em microcomputadores pessoais e em dispositivos móveis. Saiba mais Está disponível uma linha do tempo razoavelmente detalhada do desenvolvimento do Java desde sua concepção até o momento atual. O texto, em inglês, está disponível no seguinte endereço: EVANS, B. Java: the legend. O’Reilly. 2020. Disponível em: https:// www.oreilly.com/library/view/java-the-legend/9781492048299/ch01.html. Acesso em: 10 ago. 2020. 11 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS 1.2 Arquitetura de um programa em Java Um dos aspectos mais marcantes do Java e que esteve presente desde a sua concepção é o fato de essa linguagem ser multiplataforma. Plataforma é o conjunto formado por um computador e o sistema operacional instalado nesse computador. Podemos, então, ter as seguintes plataformas como exemplo: • Computador padrão PC-Intel executando Windows. • Computador padrão PC-Intel executando Linux. • Computador padrão iMac executando MacOS. • Computador padrão workstation executando Solaris etc. Dizer que o Java é multiplataforma significa dizer que um programa feito em Java e compilado em uma determinada plataforma poderá ser executado nessa plataforma e também em todas as demais plataformas que dão suporte ao Java. Observação Várias linguagens, como o C++, por exemplo, estão disponíveis para diversas plataformas. Entretanto, um código escrito em C++ que seja compilado em uma determinada plataforma só poderá ser executado nessa mesma plataforma. Para que o código seja executado em uma outra plataforma, ele deverá ser compilado novamente, mas dessa vez na plataforma em que se deseja executar o código. Mas como é possível que um programa compilado em Java em uma determinada plataforma possa ser executado em outras plataformas? O Java realiza essa façanha porque ele não é compilado diretamente para a linguagem de máquina de uma plataforma específica. Em vez disso, ele é compilado para uma linguagem de máquina de um computador fictício, uma máquina virtual. Para que o programa possa ser então executado, um computador deve utilizar um emulador desse computador fictício, que, então, interpreta o código compilado Java. Em outras palavras, um programa em Java é semicompilado, o que significa que o código-fonte é compilado para uma linguagem intermediária, conhecida como bytecode. Esse bytecode é um código de computador escrito em linguagem de máquina da Máquina Virtual Java (Java Virtual Machine – JVM). A Máquina Virtual Java, então, interpreta o bytecode e executa o programa. 12 Unidade I Código-fonte Compilador Java Bytecode Programa em execução Máquina Virtual Java Figura 2 – Processo de compilação e execução de um programa em Java Com essa estrutura, um programa compilado em Java pode ser executado diretamente em qualquer sistema que possua uma Máquina Virtual Java disponível. Lembrete Um computador só consegue executar programas que estejam escritos em linguagem de máquina. Quando um programa é escrito em uma linguagem de alto nível, o código desse programa deve ser compilado (traduzido) para a linguagem de máquina da plataforma que irá executar o programa. 1.3 Características da linguagem Java Mendes (2009) sumariza algumas das principais características do Java, características estas que justificam a grande penetração da tecnologia no mercado. Resumidamente, temos: • Simplicidade: a linguagem Java é considerada simples porque permite que o programador crie sistemas para diferentes plataformas sem se preocupar com a arquitetura do hardware particular de cada uma delas. O Java também não tenta “reinventar a roda”, criando uma nova sintaxe. Ele utiliza a sintaxe já bem estabelecida da linguagem C. Além disso, o Java não implementa alguns aspectos menos utilizados da orientação a objetos, como herança múltipla, sobrecarga de operadores, ponteiros e operações aritméticas sobre os ponteiros. • Orientação a objetos: o paradigma orientado a objetos de análise de sistemas (e de programação) traz uma nova maneira de pensar o desenvolvimento de sistemas. Essa nova maneira de criar programas utiliza os conceitos de herança, polimorfismo e encapsulamento. Esses conceitos incentivam boas práticas de programação, como o reúso de código e a padronização, o que torna sistemas orientados a objetos mais fáceis de serem desenvolvidos e reutilizados, além de apresentarem manutenção mais rápida e barata. • Multithread: o Java é uma linguagem que permite o multiprocessamento (multithreading). Isso significa que partes de um mesmo programa podem ser executadas simultaneamente. Essa técnica permite o total aproveitamento de sistemas dotados de múltiplos processadores. 13 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Deve-se ressaltar que o multiprocessamento traz benefícios também para programas executados em sistemas com apenas um núcleo de processamento. • Robustez: a linguagem Java e sua arquitetura de compilação para um código intermediário (bytecode) otimizado garantem que uma grande quantidade de erros comuns em outras linguagens não ocorra em Java, como código não alcançável e vazamentos de memória. Este segundo tipo de erro, muito comum em programas feitos em C++, ocorre quando o programador reserva um espaço de memória de trabalho para seu programa e se esquece de liberá-lo após o uso. Com o tempo, esses espaços não liberados vão se acumulando, tornando o sistema cada vez menos estável, até que ele não possa mais ser utilizado. Em Java, esse tipo de erro é extremamente improvável, pois um mecanismo automatizado chamado de garbage collector (coletor de lixo) garante que espaços de memória reservados pelo programa e que não estão mais em uso sejam automaticamente liberados. • Segurança: a linguagem Java está preparada para ser utilizada em aplicações corporativas de grande porte, com arquitetura distribuída, situação em que a segurança é de extrema importância. Saiba mais Vários livros que abordam a programação em Java apresentam a história do desenvolvimento da linguagem, assim como suas principais características, entre eles destacamos: DEITEL, H. M.; DEITEL, P. J. Java: como programar. 8. ed. São Paulo: Pearson Prentice Hall, 2010. MENDES, D. R. Programação Java com ênfase em orientação a objetos. São Paulo: Novatec, 2009. 1.4 O que é necessário para programar em Java O Java é disponibilizado por seu atual desenvolvedor, a Oracle, em diversas distribuições. Algumas delas são: • Java Standard Edition (Java SE). • Java Enterprise Edition (Java EE). • Java Micro Edition (Java ME). • Java Card. • Java TV etc. 14 Unidade I A mais importante distribuição é o Java SE (Java Edição Padrão). É nessa distribuição que estão as bibliotecas básicas do Java e as principais ferramentas de desenvolvimento, como o compilador Java. As demais distribuições são complementos ao Java SE que disponibilizam outras capacidades à linguagem. Por exemplo, o Java EE (Java Edição Corporativa) inclui bibliotecas e servidores capazes de permitir a criação e a operação de sistemas corporativos distribuídos, o uso de persistência automatizada, a criação de páginas dinâmicas de internet, entre outras funcionalidades. O Java ME (Java Edição Micro) oferece a base para a programação de dispositivos móveis, como celulares, PDAs, receptores de TV, TVs inteligentes etc. No caso de dispositivos como TVs, DVDs e Blu-Rays, há uma distribuição específica, o Java TV, que é uma especialização do Java ME para essas aplicações particulares. Observação Para desenvolver em qualquer tecnologia Java, a única distribuição obrigatória é o Java SE. Este kit de desenvolvimento (SDK – Software Development Kit) é a única distribuição que contém o compilador Java. Qualquer outra distribuição é um acessório que deve ser instalado junto ao SDK Java SE. Tendo o SDK Java SE (também conhecido como Java Development Kit – JDK) instalado, já é possível escrever programas usando algum editor de arquivos texto e usando o compilador Java por meio de linha de comando. Saiba mais O SDK Java SE pode ser obtido na página de seu desenvolvedor: http://www.oracle.com/technetwork/java/javase/overview/index.html Recentemente, a Oracle vem alterando sua estratégia de lançamento de versões, o que pode ocasionar algumas dificuldades tanto para o desenvolvedor quanto para os usuários do Java. Para que seus projetos não fiquem dependentes exclusivamente das distribuições Java da Oracle, recomenda-se sempre baixar a versão do JDK igual à versão do JRE, disponível gratuitamente para o público em geral. Até o ano de 2020, a versão mais recomendada é o Java SE 8u251. Apesar de o SDK Java SE ser suficiente para programar em Java, a maioria dos estudantes e programadores admitem que o uso de um Ambiente Integrado de Desenvolvimento (Integrated Development Environment – IDE) torna o trabalho do desenvolvedor mais fácil. Um IDE é um sistema que reúne em um único pacote diversas ferramentas, como:15 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS • editor de código-fonte; • gerenciador de arquivos; • corretor de sintaxe; • ferramenta de automação de compilação; • ferramenta de automação de depuração etc. Assim, mesmo sendo um opcional, vamos adotar uma IDE para desenvolver os exemplos. Existem diversas IDEs disponíveis, tanto de código aberto quanto de código proprietário. Várias delas podem ser utilizadas, mas para não gastarmos tempo discutindo as diferenças entre elas, vamos utilizar o Eclipse. Saiba mais O Eclipse pode ser obtido na página de seu desenvolvedor: http://www.eclipse.org O Eclipse não é o único IDE de código aberto de grande popularidade. Outro IDE bastante conhecido é o NetBeans, mantido principalmente pela Oracle, mesmo desenvolvedor do Java. Há algumas diferenças entre eles, mas não é possível dizer que um é melhor do que o outro. O que pode ser dito é que ambos são equivalentes, ou seja, tudo o que é feito com um pode ser feito com o outro. Saiba mais Para mais informações sobre o NetBeans, acesse: https://netbeans.org 16 Unidade I 1.4.1 Instalando o JDK Java SE Vá até o site de download do Java (http://www.oracle.com/technetwork/java/javase/downloads/ index.html). Clique no link Java Platform (JDK). Marque sua aceitação do contrato de licença e escolha o JDK apropriado para a plataforma que você deseja utilizar para desenvolver os seus programas. O download do arquivo de instalação do JDK deve iniciar. Inicie o arquivo de instalação e siga as instruções na tela. Figura 3 – Assistente de instalação do SDK Java SE 1.4.2 Instalando o Eclipse Vá até o site de download do Eclipse (http://www.eclipse.org/downloads/). Selecione o download para Eclipse IDE for Java Developers na versão correta para seu sistema operacional. Escolha um site espelho para realizar o download, se estiver disponível. Quando o download estiver completo, descompacte o conteúdo do arquivo em alguma pasta fácil de lembrar. O Eclipse não possui arquivo de instalação. Você deve iniciá-lo diretamente do local do qual foi extraído. 17 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 4 – O Eclipse deve ser iniciado a partir do local do qual ele foi extraído Lembrete O Java e todo o seu ecossistema (IDEs, complementos, servidores etc.) foram desenvolvidos como código aberto, ou seja, qualquer um pode obter seu código-fonte, modificá-lo e até redistribuir as suas modificações segundo as regras do código aberto. Uma das consequências de ser código aberto é que o Java é gratuito. Por essa razão, como durante um tempo o Brasil exigiu que todo o software governamental fosse de código aberto, justamente por ser gratuito, muitos dos aplicativos e sistemas governamentais são feitos em Java. 2 A LINGUAGEM JAVA Vamos criar nosso primeiro programa, o famoso Olá mundo. Comece iniciando o Eclipse. Caso nunca o tenha iniciado antes, ele deve apresentar uma página de boas-vindas semelhante à da figura a seguir: 18 Unidade I Figura 5 – Seleção do workspace (pasta de trabalho) Essa janela pede para que você indique qual é a pasta que deseja utilizar para guardar os seus projetos Java. Utilize o local padrão ou indique o local que deseja utilizar. Se marcar a check box, o Eclipse não irá mais fazer essa pergunta ao iniciá-lo. A seguir, o Eclipse inicia. De novo, caso seja a primeira vez que o esteja executando, ele deve apresentar uma tela de boas-vindas, como a da figura a seguir: Figura 6 – Página de boas-vindas do Eclipse 19 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Clique no ícone Workbench para exibir a área de trabalho. Figura 7 – Área de trabalho do Eclipse Vamos criar um projeto. Clique no menu File → New → Java Project. O seguinte assistente surge: 20 Unidade I Figura 8 – Assistente de criação de projeto Na caixa de texto Project name digite o nome do seu projeto, “Ola mundo”. Certifique-se de que na área JRE você esteja usando alguma máquina virtual Java SE. Se por algum motivo a JRE padrão em seu computador não for um Java SE, selecione o primeiro botão de rádio e escolha uma versão J2SE ou Java SE, qualquer uma dessas versões deve ser suficiente. 21 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Observação Em qualquer linguagem de programação, sempre é recomendado não utilizar caracteres acentuados ou especiais. Ainda é possível, mesmo que incomum, que haja problemas tanto na compilação quanto na execução de códigos que utilizem tais símbolos. A única exceção é quando escrevemos algum texto em um String, por exemplo. Se desejamos escrever a mensagem “Olá, mundo!” na tela, podemos usar acentos e caracteres especiais. Figura 9 – Seleção de uma máquina virtual específica 22 Unidade I As demais opções não precisam ser modificadas. Você já pode clicar no botão Finish. Nesse momento, o Eclipse criou uma pasta chamada “Ola mundo” na pasta que você indicou como pasta de trabalho. Dentro dela serão armazenados seus códigos-fonte, classes compiladas, arquivos de configuração, entre outros. Note que no Package Explorer (Explorador de Pacotes) agora há o seu projeto “Ola mundo”. Clique no sinal à esquerda do projeto para expandir sua estrutura interna. Figura 10 – Projeto com sua estrutura expandida Agora vamos criar o arquivo no qual será escrito o código-fonte do programa. Note que dentro do projeto “Ola mundo” há uma pasta chamada src. Ela é uma abreviação de source (fonte) e é nela que iremos colocar todos os códigos-fonte de um projeto. Com o botão direito do mouse, clique na pasta src e selecione new → package. Package (pacote) é um conceito da orientação a objetos que permite que o desenvolvedor agrupe suas classes em pacotes. Os conceitos de classe e pacote serão vistos detalhadamente mais adiante. 23 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 11 – Criação do pacote Na caixa para definir o nome do pacote, digite “primeiroPrograma”. Note que em Java, nomes devem ser compostos de apenas uma palavra. Clique em Finish. Observação Em linguagens que derivam do C, como o C++, C# e Java, os nomes de classes, variáveis, métodos, atributos e demais elementos devem ter como nome um termo composto de uma única palavra. Recomenda-se que os nomes sejam sempre mnemônicos, ou seja, o próprio nome deve indicar qual é a natureza ou a finalidade do elemento que ele batiza. Por exemplo, uma variável não mnemônica chamada “xpto12” não dá nenhuma indicação ao programador de sua finalidade. Já se ela for chamada de “contadorDeaIteracoes”, sua finalidade torna-se evidente. Quando se utiliza mais de uma palavra como nome, recomenda-se que a primeira letra de cada palavra, a partir da segunda palavra, seja escrita em maiúscula. Essa notação é conhecida como camel case. Em Java, 24 Unidade I recomenda-se que a primeira letra da primeira palavra seja maiúscula se o nome for de uma classe ou de uma interface. Ela deve ser minúscula para os demais casos. A exceção à notação camel case ocorre quando criamos o nome de uma constante. Nesse caso, recomenda-se que o nome seja escrito com todas as letras maiúsculas, utilizando o símbolo do sublinhado para separar as palavras. Por exemplo, os seguintes nomes são apropriados para constantes: NOTA_MINIMA, TAXA_MINIMA_DE_CRESCIMENTO, PI, CONSTANTE_GRAVITACIONAL. Dentro do pacote “primeiroPrograma” vamos criar a classe “OlaMundo”. Clique com o botão direito no pacote e selecione new → Class. Figura 12 – Criação da classe “OlaMundo” 25 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Na caixa para definir o nome da classe, digite o nome “OlaMundo”. Clique em Finish. Nesse momento, o Eclipse cria o arquivo OlaMundo.java e o exibe no editor. Já há um pouco de código escrito no arquivo, a declaração do pacote e da classe. A seguir, basta escrever o código do método principal main() como mostrado a seguir: Figura 13 – Código do programa “OlaMundo” A seguir, para compilar e executar seu programa,clique no botão indicado pela primeira seta (ou selecione o menu run → run). O Eclipse irá executar o compilador Java sobre seu código e executar o programa compilado. A saída do console é exibida na aba destacada pela segunda seta. Caso a janela para o seu código esteja pequena demais, você pode dar um duplo clique na aba da janela, o que faz com que ela seja maximizada. Para voltar à visualização anterior, basta dar um duplo clique na aba novamente. As abas também podem ser fechadas definitivamente, clicando no símbolo “X”. Caso você tenha fechado acidentalmente uma aba e não saiba como fazer para que ela seja reapresentada, você pode pedir ao Eclipse para restaurar a configuração padrão das janelas. Para tanto, chame o menu Window → Perspective → Reset Perspective... e responda Yes quando lhe for perguntado se quer realmente retornar às janelas para a configuração padrão. 2.1 Entrada e saída de dados usando JOptionPane No exemplo anterior, utilizamos um método para criar uma saída de texto no console. Também é possível receber dados do usuário pelo console. Mas para tornar este livro-texto mais enxuto, vamos deixar de lado essa forma de interação homem-máquina e priorizar o uso de interfaces gráficas. 26 Unidade I Saiba mais A Interação Humano-Computador (IHC) é uma disciplina extensa que trata de diversos aspectos da interação entre pessoas e equipamentos tecnológicos. A seguir, alguns livros que tratam desse assunto: BENYON, D. Interação humano-computador. 2. ed. São Paulo: Pearson Prentice Hall, 2011. ROGERS, Y.; SHARP, H.; PREECE, J. Design de interação: além da interação humano-computador. 3. ed. Porto Alegre: Bookman, 2013. SOUZA, L. S. de. Projeto de interface com o usuário. São Paulo: Sol, 2015. O Java nos oferece uma ferramenta pronta para criar caixas de diálogo. As caixas de diálogo são um tipo especial de janela em ambiente gráfico. Elas servem para apresentar informações e também para receber dados do usuário. Essas funcionalidades estão disponíveis na classe JOptionPane que está definida no pacote javax.swing, como ilustrado na figura a seguir: javax JOptionPane +showMessageDialog() +showInputDialog() Figura 14 – A classe JOptionPane dentro do pacote javax.swing Na figura anterior, a classe JOptionPane é representada em um diagrama de classes, tendo seus atributos omitidos e apenas dois de seus métodos representados. A classe está definida no pacote swing que, por sua vez está definido no pacote javax. 27 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Observação A UML (Unified Modeling Language – Linguagem Unificada de Modelagem) define diversos diagramas úteis para documentação, modelagem, análise e projeto de sistemas orientados a objetos. O diagrama de classes, um dos mais importantes da UML, representa as classes de um sistema em um retângulo dividido em três partes. Na primeira é anotado o nome da classe, na segunda seus atributos e na terceira seus métodos. O método showMessageDialog() permite a exibição de uma caixa de diálogo na qual uma informação é exibida para o usuário. A sobrecarga mais simples desse método é: Figura 15 – Declaração do método showMessageDialog() Esse método requer dois parâmetros: o primeiro, chamado pai, recebe um objeto que representa o elemento gráfico pai da caixa de mensagem. Esse pai costuma ser uma janela do aplicativo. Entretanto, ainda não sabemos como criar qualquer elemento gráfico, por isso, vamos utilizar a palavra reservada null para indicar que a caixa de diálogo não irá possuir qualquer componente gráfico como pai. Isso também fará com que a caixa de diálogo seja apresentada centralizada na tela. A palavra reservada null indica um objeto que não foi instanciado, um objeto nulo. O segundo parâmetro é a mensagem que será apresentada dentro da caixa de diálogo. Assim, em um programa, poderíamos utilizar o método showMessageDialog() da seguinte forma e obter o resultado exibido a seguir: Figura 16 – Exemplo de uso do método showMessageDialog() O método showInputDialog() permite criar uma caixa de diálogo que apresenta uma pergunta e exibe um espaço para que o usuário digite sua resposta. Quando o método é encerrado, ele retorna um String contendo o texto digitado pelo usuário. A declaração de sua sobrecarga mais simples é: 28 Unidade I Figura 17 – Declaração do método showInputDialog() Note que o método showInputDialog() não requer a indicação de um componente pai. Entretanto, se você desejar, pode indicar um, mesmo que seja null. O trecho de código a seguir mostra como podemos usar esse método para receber um texto do usuário. O texto digitado pelo usuário é armazenado na variável resposta: Figura 18 – Exemplo de uso do método showInputDialog() No exemplo a seguir, mostramos um programa inteiro que utiliza a classe JOptionPane para realizar entrada e saída de dados usando as caixas de diálogo. Note que, para utilizar essa classe, é necessário importá-la para que o programa possa utilizá-la. Isso é feito com a palavra reservada import, que deve ser inserida logo abaixo da palavra package. Figura 19 – Um programa que realiza entrada e saída de dados por meio de caixas de diálogo 29 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Assumindo-se que, ao executar o programa anterior, o usuário digite o nome Maria, ele irá obter as seguintes mensagens: Figura 20 – Saída gerada pelo programa OlaMundoGrafico Observação O programa da figura de um programa que realiza entrada e saída de dados deve ser criado em um pacote chamado unidadeUm. É recomendado também que ele seja criado em um novo projeto. A razão para isso é que cada projeto deve ter apenas um método main(). Quando um projeto apresenta mais de um método main(), pode ser necessário indicar ao Eclipse qual é o método main() ativo no projeto. A maneira de fazer isso varia, dependendo da versão do Eclipse. Saiba mais O uso do console como mecanismo de interação é abordado extensivamente pela maioria dos livros sobre Java. Alguns deles são: HORSTMANN, C. S.; CORNELL, G. Core Java. 8. ed. São Paulo: Pearson Prentice Hall, 2010. JORGE, M. Java passo a passo lite. São Paulo: Pearson Education do Brasil, 2004. 30 Unidade I 2.2 Recomendações de estilo Podemos dar nomes a diversos elementos de nossos programas, como variáveis, atributos, métodos, parâmetros etc. Lembrete Recomenda-se o uso de nomes mnemônicos, ou seja, nomes que já indicam qual é a finalidade do elemento que ele batiza. Por exemplo, pode ser difícil saber qual é a finalidade de uma variável chamada xpto12. Por outro lado, se a mesma variável receber o nome contadorDeaIteracoes, sua finalidade torna-se bastante clara. Para criar nomes mnemônicos, muitas vezes, desejamos usar mais de uma palavra. Mas um nome deve ser uma única palavra, sem espaços. Como dito anteriormente, a recomendação, nesse caso, é escrever todas as palavras juntas, sem espaço. Para marcar a separação entre as palavras, a partir da segunda palavra, a primeira letra deve ser grafada com letra maiúscula. Essa notação é conhecida como camel case. Exemplos: • contadorDeIteracoes; • respostaDoUsuario; • mediaFinal. O Java recomenda que a primeira letra do nome seja maiúscula caso o nome seja de uma classe ou de uma interface. Exemplos: • OlaMundo; • ProgramaPrincipal; • String. Não confunda interface com interface gráfica. A interface gráfica é um recurso de entrada e saída de dados que utiliza elementos gráficos e dispositivos de interação humana, como mouse e teclado. Já a interface é um conceito de orientação a objetos que será abordado mais adiante, mas que você já pode estar familiarizado(a), caso já tenha estudado análise orientada a objetos. Uma interface pode ser entendida, resumidamente, como uma classe sem atributos e que apenas declara as assinaturas dos métodos, sem implementar qualquer um deles. 31 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS A exceção ao camel case está na declaração de nomesde constantes. Constantes são atributos cujo valor não pode ser alterado. O Java recomenda que constantes sejam escritas com todas as letras maiúsculas, separando as palavras pelo símbolo do sublinhado. Exemplos: • NOTA_MINIMA; • TAMANHO_PADRAO; • PI; • CONSTANTE_GRAVITACIONAL. 2.3 Tipos primitivos Tipos são a natureza dos dados que podem ser armazenados em uma variável, um atributo, e que podem ser transferidos por um parâmetro ou retorno de método. Tipo primitivo é o tipo de dado que está definido na própria linguagem Java. Por isso, esses tipos têm um excelente desempenho, tanto em economia de memória quanto em desempenho de processamento. Estes tipos são: Tabela 1 – Tipos primitivos em Java Tipo Tamanho em bits Natureza Valores boolean Depende da JVM de cada plataforma Booleanos true ou false char 16 Caractere alfanumérico ‘\u0000’ a ‘\uffff’ (0 a 65535) byte 8 Número inteiro -128 a 127 short 16 -32.768 a 32.767 int 32 -2.147.483.648 a 2.147.483.647 long 64 -9223372036854775808 a 9223372036854775807 float 32 Número em ponto flutuante Intervalo negativo -3,4028234663852886E+38 a -1,40129846432481707e-45 Intervalo positivo 1,40129846432481707e-45 a 3,4028234663852886E+38 double 64 Intervalo negativo -1,7976931348623157E+308 a -4,94065645841246544e-324 Intervalo positivo 4,94065645841246544e-324 a 1,7976931348623157E+308 Fonte: Deitel e Deitel (2005). 32 Unidade I Na figura a seguir, criamos algumas variáveis e atribuímos a elas valores definidos por literais, ou seja, valores definidos no próprio código-fonte: Figura 21 – Exemplos de declaração de variáveis de tipos primitivos Quando se define um literal numérico inteiro, ele é tratado como um inteiro. Já quando se define um literal numérico com um ponto decimal, ele é tratado como um double. Para definir um literal caractere, ele deve ser circundado por aspas simples. Um literal booleano só pode assumir os valores representados pelas palavras reservadas true ou false. Quando se deseja definir um literal inteiro maior do que a capacidade de representação do int, deve-se indicar que o literal é um long, adicionando-se o sufixo L ou l. Analogamente, ao representar um literal como um float, deve-se adicionar o sufixo F ou f: Figura 22 – Literais de tipo long e float 2.4 Conversão de tipos Quando trabalhamos com mais de um tipo primitivo, podemos atribuir o valor armazenado em uma variável de tipo de menor capacidade em uma variável de maior capacidade. De certa forma, podemos entender que um tipo menor “cabe” dentro de um tipo maior. byte short int long float double Figura 23 – Relação de capacidade entre tipos primitivos numéricos Dessa forma, o seguinte método, se executado, irá gerar a mensagem representada na figura de saída do método atribuicoesSemCast(). 33 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 24 – Atribuições de variáveis a tipos de capacidade crescentes Na linha 10 é declarado o método atribuicoesSemCast(), o qual realiza o exemplo. Na linha 11 é declarada a variável b do tipo byte com o valor 8. Da linha 12 até a linha 16, o valor da variável b é transferido sucessivamente para variáveis de maior capacidade. Na linha 18 é declarada uma variável do tipo String chamada valores. A esta variável é atribuído o retorno do método format() da classe String. O método format() recebe pelo menos dois parâmetros. O primeiro é um String de formatação. Esse String é composto de caracteres que são simplesmente retornados, como “b =” e parâmetros de formatação que são compostos de um sinal % e uma letra. Essa letra indica se o parâmetro será substituído por um número decimal (d) ou um número de ponto flutuante (f). A seguir, o método format() recebe os valores que serão inseridos nos parâmetros do String de formatação. As sequências “\n” indicam que será inserida no String uma quebra de linha. Por fim, para que o código não fique demasiadamente largo, pode-se quebrar uma linha no meio do String. Para tanto, ele deve ser encerrado na primeira linha, fechando as aspas, e na linha seguinte deve ser concatenado com o segundo String, usando o operador +. Figura 25 – Saída do método atribuicoesSemCast() 34 Unidade I Já para fazer as atribuições na direção oposta, é necessário realizar um cast, ou conversão de tipo. Um cast é representado pelo tipo de destino entre parênteses antes do valor a ser convertido. O programa da figura de atribuições de variáveis foi alterado para realizar atribuições de variáveis de maior capacidade a variáveis de menor capacidade. Figura 26 – Atribuições de variáveis de maior capacidade a variáveis de menor capacidade Na figura anterior está representado o mesmo programa Atribuicoes. Repare que na linha 11 há um sinal +, e a próxima linha é a 24. Esse sinal indica que a implementação do método atribuicoesSemCast() foi ocultada. Esse recurso está disponível no Eclipse e em praticamente qualquer IDE moderna. Para exibir novamente o código oculto, basta clicar no sinal +. Para ocultar um trecho de código, clica-se no sinal -. A outra modificação está no método main(), que agora chama também o método atribuicoesComCast(). Na linha 26 é declarada uma variável double com um valor em ponto flutuante. Nas linhas 27 a 31 esse valor é convertido sucessivamente em tipos cada vez de menor capacidade. O resultado pode ser visto na figura a seguir: 35 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 27 – Saída do método atribuicoesComCast() Note como os valores, ao serem convertidos para tipos de menor capacidade, foram perdendo precisão, como se estivessem sendo corrompidos. Isso ocorre porque o cast não faz arredondamento, ele faz truncamento em binário. Isso significa que, quando um número é convertido para um tipo de capacidade menor em bits, apenas os bits menos significativos são mantidos. Os bits excedentes do número são desprezados, o que causa a perda de informação. Observação A partir de agora, os exemplos apresentados neste livro-texto não serão mais programas inteiros. Os exemplos serão apresentados como métodos que podem simplesmente ser inseridos em um programa qualquer que você já tenha criado. Basta chamar o método a partir do seu método main(). 2.5 Classes wrapper (invólucro) Cada tipo primitivo possui uma classe wrapper associada. Uma classe wrapper pode ser utilizada para instanciar um objeto que armazena um valor do tipo primitivo associado a ela. Além disso, essas classes apresentam diversos métodos para fazer a conversão de diversos tipos. As classes wrapper são: Quadro 1 – Tipos primitivos e suas classes wrapper associadas Tipo primitivo Classe wrapper boolean boolean char character byte byte short short int integer long long float float double double 36 Unidade I Essas classes podem ser utilizadas para instanciar objetos com um valor do tipo primitivo associado a elas: Figura 28 – Instanciação de objetos de classes wrapper A partir do Java 5 (Java versão 1.5), o valor de uma variável de tipo primitivo pode ser atribuído diretamente a um objeto de sua classe wrapper associada e vice-versa. Esse recurso é chamado de autoboxing: Figura 29 – Exemplo de autoboxing As classes wrapper oferecem métodos parse que são úteis para converter um String em um valor de tipo primitivo associado. Cada classe wrapper possui um método parse: Figura 30 – Exemplos de conversão de String para tipos primitivos As classes wrapper numéricas (exceto Boolean e Character) possuem métodos value para converter o valor armazenado no objeto para outros tipos primitivos numéricos. Dessa vez, a conversão é feita com arredondamento, não mais com truncamento, como o que ocorre quando um cast é utilizado. O exemplo a seguir utiliza os métodos value para converter de um objeto Integer para diversos outros tipos, mas o mesmo pode ser feito com qualquer outro wrapper numérico. Figura 31 – Exemplo de uso de um objeto wrapper para converter um inteiro para diversos outros tipos37 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Repare que, na primeira linha, foi usado um construtor da classe Integer, que recebe um String, e não um int. Todas as classes wrapper possuem um construtor que recebe um String. Esse construtor faz a conversão apropriada, usando um método parse adequado, antes de terminar a instanciação do objeto. Saiba mais Como em qualquer recurso do Java, é possível aprender bastante estudando a documentação da linguagem. Para saber do que mais são capazes as classes wrapper, consulte: LESSON: numbers and strings. The Java TM Tutorials. 2019. Disponível em: https://docs.oracle.com/javase/tutorial/java/data/index.html. Acesso em: 10 ago. 2020. Veja o programa a seguir, que utiliza uma classe wrapper para receber dois números do usuário e realizar um cálculo matemático: Figura 32 – Um programa que recebe números do usuário e realiza um cálculo matemático com eles 38 Unidade I Figura 33 – Saídas do programa da figura anterior 2.6 Introdução a classes e objetos Uma das diferenças mais óbvias entre uma linguagem estruturada e uma linguagem orientada a objetos é justamente o conceito de classes e objetos. Pode-se entender, de maneira bastante simplificada, que uma classe é um trecho de código de computador que modela algum conceito útil para o sistema que está se desenvolvendo. Esse conceito pode ser algo tangível, como um cliente, um funcionário, um produto, uma venda, mas também pode ser um conceito mais abstrato, como um conjunto de ferramentas de cálculo ou um conjunto de funcionalidades de acesso a banco de dados. Quando se faz a análise de um sistema, devem-se modelar classes que encapsulem, isolem, coloquem uma “cápsula” em torno desse conceito. Para tanto, devem-se ter em mente as seguintes regras para um bom projeto de classe: • Uma classe deve modelar apenas um conceito. • Uma classe não deve modelar qualquer aspecto de outro conceito. 39 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS • Não deve haver em nenhuma outra parte do sistema qualquer aspecto do conceito modelado pela classe. Saiba mais Os seguintes livros abordam em detalhes as tarefas relacionadas à criação da estrutura de classes de um sistema: MEDEIROS, E. S. de. Desenvolvendo software com UML 2.0: definitivo. São Paulo: Makron Books, 2004. PAGE-JONES, M. Fundamentos do desenho orientado a objeto com UML. São Paulo: Makron Books, 2001. SINTES, T. Aprenda programação orientada a objetos em 21 dias. São Paulo: Pearson Education do Brasil, 2002. Uma classe modela um determinado conceito reunindo em um único elemento os dados que definem esse conceito e os comportamentos que ele pode apresentar. Uma boa maneira de representar classes é usando o Diagrama de Classes da UML (Unified Modeling Language – Linguagem Unificada de Modelagem). Nesse diagrama, uma classe é representada com um retângulo dividido em três partes. Na primeira parte é registrado o nome da classe. Na segunda, os atributos da classe que armazenam os dados da classe. Na terceira parte, os métodos da classe que implementam os comportamentos da classe. Figura 34 – Diagrama de classes da classe Pessoa A figura anterior registra uma classe em UML. Essa classe tem o nome Pessoa e possui dois atributos: nome e telefone. O primeiro atributo armazena dados do tipo String, enquanto o segundo armazena dados do tipo int. A classe também apresenta o método apresente(), que será usado para exibir as informações armazenadas nos atributos. Esse método não recebe parâmetros, pois não há nenhum parâmetro representado entre os parênteses. Ele também não devolve nenhum valor, pois seu tipo de retorno é void. Essa classe pode ser codificada em Java da seguinte maneira: 40 Unidade I Figura 35 – A classe Pessoa codificada em Java Nas linhas 7 e 8 estão declarados os atributos nome e telefone. Eles são declarados como se fossem variáveis, mas são atributos por não estarem dentro de qualquer método. Suas declarações são precedidas pela palavra reservada public, representada pelo sinal + no diagrama UML da figura 34. Essa palavra reservada indica que esses atributos podem ser acessados por qualquer parte do sistema que tenha acesso à classe Pessoa. Na linha 10 é declarado o método apresente(), que imprime em uma caixa de diálogo os dados armazenados nos atributos. Uma classe é uma definição de um conceito, como o simples cadastro de uma pessoa, apresentado anteriormente. Mas um programa não pode utilizar essa definição diretamente, ele precisa instanciar essa classe em um objeto. Imagine que uma classe seja uma receita de bolo. Com essa receita, podem-se preparar vários bolos, e todos acabarão sendo mais ou menos parecidos. Dessa mesma forma, uma classe é usada para instanciar vários objetos. É o objeto que realmente possui os dados e os comportamentos modelados. O programa a seguir instancia um objeto da classe Pessoa, atribui valores aos seus atributos e chama o método apresente(). O resultado de sua execução também é apresentado: 41 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 36 – Programa TestaPessoa e o resultado de sua execução Na linha 7 é criada uma variável chamada p, cujo tipo é Pessoa. Nessa variável é armazenado um objeto da classe Pessoa. O objeto é instanciado com o uso da palavra reservada new seguida do “nome da classe”. Na verdade, o termo Pessoa() que segue a palavra new não é o nome da classe, mas um método construtor. Nas linhas 9 e 10 os atributos nome de p e telefone de p têm seus valores atribuídos. Note que o objeto p têm seus próprios atributos nome e telefone. Caso um outro objeto fosse instanciado, ele poderia ter valores diferentes em seus atributos nome e telefone. Na linha 12 é chamado o método apresente() de p, o qual faz ser exibida a caixa de mensagem com as informações armazenadas no objeto p. 2.7 Instruções de controle Note que, da maneira que a classe Pessoa foi escrita, qualquer valor pode ser atribuído aos atributos da classe, mesmo que eles sejam inválidos. Há uma maneira de evitar que isso aconteça: nós podemos encapsular os atributos, ou seja, torná-los privados e oferecer acesso a eles por métodos acessores que fazem a validação dos dados, de forma que apenas dados válidos sejam armazenados. A seguir, modificamos a classe Pessoa para que só possam ser armazenados telefones com pelo menos oito dígitos. Vamos também encapsular o atributo nome, mesmo que nenhuma validação seja feita: 42 Unidade I Figura 37 – A classe Pessoa com atributos encapsulados Nas linhas 7 e 8 os atributos nome e telefone foram alterados para privados, o que significa que agora eles só podem ser acessados de dentro da própria classe Pessoa. Para permitir que eles tenham seus valores lidos, foram criados os métodos getters, nas linhas 10 e 18. Esses métodos, quando executados, retornam o valor armazenado no atributo correspondente. Na linha 14 é criado o método setNome(), que recebe como parâmetro um nome e o atribui ao atributo nome. Como tanto o parâmetro quanto o atributo possuem o mesmo nome, o programa não teria como saber qual é o atributo e qual é o parâmetro. Para resolver esse problema, utiliza-se a referência this, na linha 15. Dessa forma, pode-se ler a linha 15 como “o nome deste objeto recebe o valor de nome”. Assim, this.nome é o atributo do objeto, enquanto nome é o parâmetro. Já no método setTelefone(), na linha 22, só é feita a atribuição se o valor do parâmetro telefone tiver ao menos oito dígitos. Essa verificação é feita com o desvio condicional if. Sua sintaxe completa é: 43 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Figura 38 – Sintaxe do desvio condicional if A condição pode ser qualquer expressão que tenha como valor final um booleano. Isso significa que a condição pode ser uma simples variável booleana ou uma expressão booleana, que é o resultado de alguma operação lógica. As operações lógicas são: Tabela 2 – Operadores lógicos == Igual a != Diferente de< Menor que > Maior que <= Menor ou igual a >= Maior ou igual a ! Não (inverte o resultado de uma expressão booleana) Quando se deseja realizar vários testes, pode-se encadear outro if dentro do conjunto de instruções da cláusula else. Mas também pode-se utilizar a estrutura switch-case, a qual tem a sintaxe a seguir: Figura 39 – Sintaxe da estrutura switch-case A estrutura switch-case usa como cláusula de teste uma variável que pode ser dos tipos primitivos char, int, short ou byte. Cada cláusula case define um conjunto de instruções que será executado caso seu valor corresponda ao valor da variável de teste. A cláusula default, que é opcional, é executada se nenhuma outra cláusula case foi executada. 44 Unidade I Saiba mais A sintaxe completa das estruturas if, if-else e switch-case pode ser encontrada nos seguintes documentos de apoio: THE IF-THEN and if-then-else statements. The Java™ Tutorials. 2019. Disponível em: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/ if.html. Acesso em: 10 ago. 2020. THE SWITCH statement. The Java™ Tutorials. 2019. Disponível em: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html. Acesso em: 10 ago. 2020. A classe Pessoa ainda não teve um método construtor definido explicitamente. Método construtor é um método que é executado sempre que um objeto é instanciado. Esse método deve possuir exatamente o mesmo nome da classe e não deve apresentar nenhum tipo de retorno, nem mesmo void. Quando não criamos um construtor em uma classe, o próprio compilador cria um para nós, é o construtor padrão. O método construtor padrão é um construtor sem parâmetros e que não executa nenhuma ação em sua implementação. Quando escrevemos “Pessoa p = new Pessoa();”, o termo Pessoa(), na verdade, é o construtor padrão da classe. Nós podemos criar os nossos próprios construtores. Uma vez que a classe tenha um construtor qualquer, o compilador não irá criar o construtor padrão. Caso queiramos um construtor sem parâmetros, devemos declará-lo explicitamente, como no exemplo a seguir: Figura 40 – A classe Pessoa com métodos construtores 45 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Na linha 28 é declarado o método construtor sem parâmetros. Note que o método deve ter exatamente o mesmo nome da classe e não deve apresentar nenhum tipo de retorno. Na linha 32 é criado um segundo método construtor, desta vez ele recebe como parâmetros o nome e o telefone da pessoa. Em sua implementação, ele faz a atribuição dos valores utilizando a validação de dados por meio dos métodos acessores que já foram criados na classe. A classe TestaPessoa pode ser modificada da seguinte maneira, para refletir as mudanças feitas na classe Pessoa: Figura 41 – Programa TestePessoa corrigido Na linha 7 é instanciado o objeto p1, utilizando o construtor sem parâmetros. Nas linhas 8 e 9 os valores dos atributos agora precisam ser definidos utilizando os métodos acessores. Já não é mais possível acessar os atributos diretamente, pois eles foram definidos como privados. Na linha 12 um outro objeto, p2, é instanciado, desta vez utilizando o construtor que recebe como parâmetros os valores do nome e do telefone. Durante a instanciação os valores são armazenados nos atributos, e o objeto já está pronto para exibir suas informações. 46 Unidade I Agora, digamos que queremos que o programa leia e exiba os dados de dez pessoas. Nós poderíamos simplesmente repetir a lógica do programa anterior dez vezes, mas essa não é a melhor escolha. Observação O computador existe para realizar o trabalho árduo para nós. Sempre que estamos pensando algo como “vou ter que fazer a mesma coisa de novo”, muito provavelmente há algo errado em nosso algoritmo. Sempre há alguma maneira de fazer com que o programa faça a tarefa repetitiva para nós. A seguir vamos modificar o programa TestePessoa para repetir dez vezes a rotina de receber e exibir os dados de dez pessoas: Figura 42 – Programa que recebe e exibe os dados de dez pessoas 47 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS O método recebePessoa() entre as linhas 7 e 19 recebe do usuário os dados de uma pessoa, instancia um objeto da classe Pessoa com esses dados e o retorna. O método main(), entre as linhas 21 e 30, utiliza o método recebePessoa() para receber os dados de dez pessoas. Na linha 25 é iniciado um laço de repetição for para repetir dez vezes a rotina definida nas linhas 26 e 27. O laço for tem três parâmetros: o primeiro é uma definição de uma variável contadora; o segundo é a condição que, se verdadeira, permitirá que o laço seja repetido mais uma vez; e o terceiro é a lógica de incremento (ou decremento) da variável contadora. O Java ainda define os laços while e do-while, que possuem a seguinte sintaxe: Figura 43 – Sintaxe dos laços while e do-while O laço while inicia testando a condição de parada. Se ela for verdadeira, ele irá executar o conjunto de instruções de repetição. Em algum momento durante a execução, a condição de parada deve ser alterada para falsa, de modo a fazer com que o laço encerre. O laço do-while inicia executando uma vez o conjunto de instruções de repetição. A seguir ele verifica a condição de parada. Se ela estiver verdadeira, o loop reinicia. Novamente, em algum momento, a condição de parada deve ser alterada para falsa, para que o laço termine. Saiba mais Consulte a documentação do Java para conhecer mais detalhes dos laços for, while e do-while: THE FOR statement. The Java™ Tutorials. 2019. Disponível em: https:// docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html. Acesso em: 10 ago. 2020. THE WHILE and do-while statements. The Java™ Tutorials. 2019. Disponível em: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/ while.html. Acesso em: 10 ago. 2020. 48 Unidade I 2.8 Arrays O programa do exemplo anterior conseguia ler e exibir os dados de dez pessoas, mas não era capaz de armazená-los. Para tanto, deveríamos ter criado dez variáveis. Contudo, criando dez variáveis, seria muito difícil continuar utilizando o laço for para automatizar o processo. Para resolver esse problema, podemos utilizar um array (vetor). Um array é um conjunto de variáveis de mesmo tipo. Vejamos como o programa pode ser modificado para utilizar um array de Pessoa: Figura 44 – Programa que recebe e armazena Pessoa em um array Na linha 22 é declarada a variável p, que desta vez é um array de objetos da classe Pessoa. Isto é indicado pelo símbolo [ ]. Um array deve ser instanciado como se fosse um objeto, o que é feito na linha 23 com o operador new, seguido do tipo de dado de cada elemento do vetor (Pessoa) e da quantidade de elementos do vetor ([10]). Na linha 25 é declarada a variável contadora que será usada nos dois laços for a seguir. Na linha 27 é iniciado o laço de leitura das dez pessoas. Na linha 28, cada pessoa é lida pelo método recebePessoa() e é armazenada no elemento de ordem i do vetor p (p[i]). Note que os índices de vetores em Java iniciam com o valor 0. Na linha 31 é iniciado o laço de apresentação das dez pessoas. Cada elemento do vetor p é um objeto da classe Pessoa e, por isso, possui o método apresente(). Assim, na linha 32, cada elemento do vetor tem o seu método apresente() chamado. 49 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Saiba mais Consulte a documentação do Java sobre a declaração e o uso de arrays: ARRAYS. The Java™ Tutorials. 2019. Disponível em: https://docs.oracle. com/javase/tutorial/java/nutsandbolts/arrays.html. Acesso em: 10 ago. 2020. 2.9 Coleções O uso de arrays foi útil para armazenar uma quantidade definida de objetos da classe Pessoa. Entretanto, para utilizar arrays deve-se saber de antemão quantos elementos serão necessários para criar o vetor. Quando não se sabe quantos elementos serão necessários, podemos utilizar estruturas dinâmicas de armazenamento de dados. O Java nos oferece um conjunto de estruturas desse tipo, as coleções. Umacoleção é um conjunto de variáveis semelhante a um array, mas que pode ter o seu tamanho modificado conforme a necessidade. Vamos modificar o programa TestaPessoa para receber uma quantidade indefinida de pessoas. Esse programa irá armazenar objetos da classe Pessoa enquanto o usuário desejar: Figura 45 – Um programa que recebe uma quantidade indefinida de pessoas 50 Unidade I Na linha 24 é declarada a estrutura dinâmica de armazenamento de dados pessoas, que é um ArrayList que irá armazenar elementos da classe Pessoa. Na mesma linha, a estrutura pessoas é instanciada. Por enquanto, a estrutura já existe, mas ainda não possui nenhum elemento dentro dela. Nas linhas 27 a 32 é feita a leitura de uma quantidade não conhecida de pessoas. Na linha 27 é declarada a variável que irá conter a resposta do usuário quando lhe for perguntado se ele deseja continuar cadastrando pessoas. Sua resposta será na forma de um número inteiro, como será visto adiante. Na linha 28 é iniciado o laço do-while, o que significa que o laço será executado ao menos uma vez. Na linha 29, o método recebePessoa() é executado para ler os dados de uma pessoa. Ele devolve um objeto da classe Pessoa, e então este objeto é passado como parâmetro para o método add() do ArrayList pessoas. Esse método adiciona seu parâmetro como um novo elemento do vetor dinâmico pessoas. Na linha 30 é usado o método showConfirmDialog da classe JOptionPane. Esse método exibe uma caixa de diálogo na qual o usuário pode dar sua resposta por meio de botões. A versão do método utilizada pede quatro parâmetros: o primeiro é a janela pai (continuamos usando nenhuma); o segundo é a pergunta que será exibida para o usuário; o terceiro é o título da caixa de diálogo; o quarto define quais são os botões exibidos. As opções são YES_NO_CANCEL_OPTION e YES_NO_OPTION. Na linha 32, a resposta do usuário é verificada. Para que não tenhamos que decorar qual é o valor de cada resposta, utilizamos uma das constantes disponíveis para a resposta: YES-OPTION, NO_OPTION ou CANCEL_OPTION. Nas linhas 35 a 37 um novo laço é feito, dessa vez para exibir os dados de todas as pessoas cadastradas. A linha 35 utiliza uma forma alternativa do laço for. Essa forma recebe dois parâmetros separados por dois-pontos (em vez de ponto-e-vírgula): o primeiro é uma definição de cada elemento da estrutura definida pelo segundo parâmetro, essa linha pode ser lida como “para cada Pessoa p em pessoas”; o segundo parâmetro pode ser uma coleção ou um vetor. Esse laço, então, irá percorrer todos os elementos dentro de pessoas, irá chamar cada um de p e irá executar a linha 36, em que é chamado o método apresenta() de p. Saiba mais Consulte a documentação disponível para coleções, o for alternativo e a classe JOptionPane: TRAIL: collections. The Java™ Tutorials. 2019. Disponível em: https://docs. oracle.com/javase/tutorial/collections/index.html. Acesso em: 10 ago. 2020. THE FOR statement. The Java™ Tutorials. 2019. Disponível em: https://docs. oracle.com/javase/tutorial/java/nutsandbolts/for.html. Acesso em: 10 ago. 2020. CLASS JOptionPane. The Java™ Tutorials. 2019. Disponível em: https://docs. oracle.com/javase/tutorial/java/nutsandbolts/for.html. Acesso em: 10 ago. 2020. 51 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS 2.10 Tratamento de exceções Se você esteve testando os programas discutidos até aqui, deve ter encontrado algumas situações em que o programa parou abruptamente devido a alguma situação inesperada. Por exemplo, em qualquer um dos programas que cadastra o telefone de uma Pessoa, se o usuário digitar uma letra (ou nada) no lugar de um número inteiro quando lhe é pedido para digitar o número de um telefone, o programa é encerrado informando uma mensagem de erro. Experimente fazer isso agora e observe a mensagem de erro que é apresentada na janela do Console. Na primeira linha da mensagem de erro é dito que ocorreu uma exceção do tipo NumberFormatException (em inglês). Isso indica que foi tentada a conversão para inteiro de um String que não representava um número inteiro. Nós podemos modificar o programa para que ele perceba essa exceção e peça ao usuário para inserir novamente o número de telefone até que um número válido seja inserido. Isso é feito com o tratamento de exceções, que é composto de blocos try-catch ou try-catch-finally. No bloco try é implementado o código que pode provocar uma exceção. No bloco catch é implementado o código que será executado caso uma exceção ocorra. No bloco opcional finally é implementado o código que deve ser executado tendo ocorrido uma exceção ou não. Ele é útil para fechar recursos que estavam sendo usados no bloco try, como arquivos, conexões com bancos de dados, conexões de rede etc. Vamos modificar o método recebePessoa() da classe TestaPessoa para que ele se recupere de uma entrada de dados errada no número do telefone. 52 Unidade I Figura 46 – Programa que trata exceções O trecho que recebe o número de telefone de uma pessoa agora está entre as linhas 19 e 29. Na linha 19 é definida uma variável booleana que é verdadeira enquanto o usuário precisa inserir um número de telefone válido. Na linha 20 é iniciado o laço que será repetido enquanto o usuário insere caracteres inválidos para um número de telefone. Na linha 21 é iniciado o bloco try, que é o trecho de código que pode causar uma exceção. A exceção de formatação numérica pode ocorrer na linha 22, quando o método parseInt() tenta converter um String inválido para um número inteiro. Se a conversão for bem-sucedida, a linha 24 é executada e armazena o valor false na variável repete. Caso uma exceção de formatação numérica tenha sido lançada no bloco try, ela será capturada pelo bloco catch na linha 25. Na linha 26 é exibida uma mensagem informativa ao usuário, e a variável repete não terá seu valor alterado. 53 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Na linha 29 o laço do-while decide se ele deve reiterar ou não, dependendo do valor armazenado pela variável repete. A variável contém o valor true se ocorreu uma exceção, e false caso contrário. As principais exceções são: • ArithmeticException: erro aritmético, como uma divisão por zero. • ArrayIndexOutOfBoundsException: foi acessado um índice de vetor fora do seu limite. • NullPointerException: foi acessado um objeto que ainda não foi instanciado. • NumberFormatException: foi tentada a conversão de um String em um formato numérico inválido. Também é possível fazer o tratamento de mais de uma exceção em um mesmo bloco try: Figura 47 – Tratamento de mais de uma exceção Nas linhas 16 e 18 é feita a conversão da entrada de dados do usuário para int, o que pode causar uma exceção NumberFormatException, a qual é tratada pela cláusula catch da linha 23. Na linha 20 é feita a divisão de dois números inteiros, o que pode causar uma exceção ArithmeticException, a qual é tratada pela cláusula catch da linha 26. 54 Unidade I Saiba mais Consulte a documentação sobre as exceções em Java: LESSON: exceptions. The Java™ Tutorials. 2019. Disponível em: https:// docs.oracle.com/javase/tutorial/essential/exceptions/index.html. Acesso em: 10 ago. 2020. Resumo Nesta unidade revimos um pouco da história da computação, que levou ao desenvolvimento do Java não só como uma nova linguagem de programação, mas como um framework para o desenvolvimento de aplicativos multiplataforma. Vimos como o Java usa a Máquina Virtual Java para interpretar aplicativos compilados em bytecode, que é o mecanismo que permite que a arquitetura Java seja multiplataforma. Conhecemos também as diversas distribuições Java e quais são os elementos indispensáveis para desenvolver em Java, assim como os elementos opcionais, que ajudam bastante no trabalho do desenvolvedor. Na sequência, vimos como instalar os principais recursos necessários para programar em Java, como a IDE e o Eclipse, que facilitam o aprendizado. A tecnologia Java foi desenvolvida para seruma tecnologia de desenvolvimento de software multiplataforma, ou seja, seu código compilado pode ser executado diretamente em qualquer plataforma que esteja equipada com uma Máquina Virtual Java (JVM, em inglês). Isso é possível porque o código-fonte Java é compilado para um bytecode. A partir daí esse bytecode é interpretado pela máquina virtual na plataforma de execução. O Java teve sua popularidade favorecida pelo surgimento da World Wide Web, que viu na tecnologia uma maneira de incorporar interatividade e multimídia às páginas web. Hoje o Java é utilizado em praticamente qualquer situação que utiliza programação, como aplicativos desktop, corporativos distribuídos, para dispositivos móveis, para eletrodomésticos, automóveis, entre outros. Para desenvolver em qualquer tecnologia Java, o mínimo necessário é instalar o Kit de Desenvolvimento Java SE (Java SE SDK ou simplesmente JDK). É possível programar utilizando um simples editor de arquivos-texto e 55 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS compilar usando o JDK. As Plataformas de Desenvolvimento Integradas (IDEs) são bastante populares. Com elas é possível realizar a maioria das atividades relacionadas ao desenvolvimento de software, como escrever código, compilar, depurar e implantar o sistema. Pode-se realizar a entrada e a saída de dados de uma maneira simples utilizando a classe JOptionPane, a qual disponibiliza métodos para a exibição de caixas de diálogo. O método showMessageDialog() exibe uma mensagem; o método showInputDialog() recebe dados do usuário; e o método showConfirmDialog() permite que o usuário responda a perguntas cuja resposta pode ser simplesmente sim, não e cancela. Todos os elementos que podem ser nomeados (variáveis, atributos, métodos, parâmetros, classes, pacotes etc.) devem ter nomes escritos sem espaços. Caso o programador escolha um nome composto por mais de uma palavra, elas devem ser escritas juntas, com a primeira letra de cada palavra a partir da segunda palavra em letra maiúscula. Caso o nome seja de uma classe, a primeira letra da primeira palavra deve ser maiúscula; essa notação é conhecida como camel case. Os tipos primitivos são os tipos de dados que a linguagem pode manipular diretamente. Dados armazenados em uma variável de tipo primitivo podem ser armazenados em outra variável de tipo primitivo de maior capacidade. Já a atribuição na direção da variável de maior capacidade para a de menor capacidade deve ser feita utilizando alguma forma de conversão, como a conversão direta ou cast. Cada tipo primitivo possui uma classe wrapper associada, a qual pode instanciar objetos que armazenam um valor do tipo primitivo associado a ela, além de oferecer diversos métodos para conversão de tipos. As classes wrapper devem ser utilizadas apenas para a conversão de tipos. Já para uso normal no aplicativo, é recomendado o uso dos tipos primitivos, os quais são muito mais eficientes em uso de memória e no desempenho de processamento. Classes são a estrutura básica de um programa orientado a objetos. Elas são compostas basicamente de atributos e métodos. Uma classe deve modelar algum conceito presente no sistema. Dessa forma, os atributos da classe modelam os dados desse conceito enquanto os métodos da classe modelam os comportamentos desse conceito. Algoritmos podem ser construídos utilizando instruções de controle. As instruções de controle do Java são inspiradas nas instruções de controle do C e seguem a sua sintaxe básica. As instruções são o if, switch-case, for, while e do-while. 56 Unidade I Conjuntos maiores de dados podem ser armazenados em estruturas homogêneas de dados, também conhecidas como vetores, ou ainda arrays. Caso seja desejada uma estrutura de armazenamento dinâmica, isto é que possa mudar de tamanho durante a execução do programa, podem-se utilizar as estruturas disponíveis no framework Collections, como a classe ArrayList. Um objeto dessa classe comporta-se como um array que pode mudar de tamanho conforme muda a quantidade de elementos armazenados por ele. Durante a execução de qualquer programa podem ocorrer situações de exceção, que podem (devem) ser tratadas pelo programa de modo que este não seja interrompido. O uso de tratamento de exceções pelo uso dos blocos try-catch e try-catch-finally tornam o sistema mais tolerante a falhas. Assim, o programa pode se recuperar de alguma situação inesperada e cumprir suas tarefas corretamente. Exercícios Questão 1. (Emprel 2009) Sabendo que, nas linguagens de programação, existem diferentes palavras reservadas, é correto afirmar que são apenas palavras reservadas em linguagem de programação Java: A) strictfp, private, byte, transient. B) function, void, real, procedure. C) protected, finally, if, yield. D) public, void, del, elif. E) void, var, int, def. Resposta correta: alternativa A. Análise das alternativas A) Alternativa correta. Justificativa: todas as palavras que aparecem na lista são palavras reservadas. B) Alternativa incorreta. Justificativa: as palavras function e real não são palavras reservadas. 57 TÓPICOS ESPECIAIS DE PROGRAMAÇÃO ORIENTADA A OBJETOS C) Alternativa incorreta. Justificativa: a palavra yield é nome de uma função da classe Thread, mas pode ser usada livremente. D) Alternativa incorreta. Justificativa: as palavras del e elif não são palavras reservadas. E) Alternativa incorreta. Justificativa: as palavras var e def não são palavras reservadas. Questão 2. (TJ-PA 2020) Assinale a opção que apresenta corretamente a saída gerada pelo código Java que segue: Figura 48 A) 36. B) 1 2 3 4 5 6. C) 1 2 3 4 5. D) 0 1 2 3 4 5. E) 0 1 2 3 4 5 6. Resposta correta: alternativa D. 58 Unidade I Análise da questão 1ª rodada i = 0 0x0 = 0 (menor que 36) 2ª rodada i = 1 1x1= 1 (menor que 36) 3ª rodada i= 2 2x2 = 4 (menor que 36) 4ª rodada i = 3 3x3 = 9 (menor que 36) 5ª rodada i = 4 4x4 = 16 (menor que 36) 6ª rodada i = 5 5x5 = 25 (menor que 36) 7ª rodada i = 6 6x6 = 36 (igual a 36). Sai do for.
Compartilhar