SlideShare uma empresa Scribd logo
UNIVERSIDADE FEDERAL RURAL DE PERNAMBUCO (UFRPE)

  COORDENAÇÃO GERAL DE EDUCAÇÃO A DISTÂNCIA (EAD/UFRPE)




           Programação II




     Fernando Antonio Mota Trinta




                                                    Volume 1




                    Recife, 2010
Universidade Federal Rural de Pernambuco


Reitor: Prof. Valmar Corrêa de Andrade
Vice-Reitor: Prof. Reginaldo Barros
Pró-Reitor de Administração: Prof. Francisco Fernando Ramos Carvalho
Pró-Reitor de Extensão: Prof. Paulo Donizeti Siepierski
Pró-Reitor de Pesquisa e Pós-Graduação: Prof. Fernando José Freire
Pró-Reitor de Planejamento: Prof. Rinaldo Luiz Caraciolo Ferreira
Pró-Reitora de Ensino de Graduação: Profª. Maria José de Sena
Coordenação Geral de Ensino a Distância: Profª Marizete Silva Santos



Produção Gráfica e Editorial
Capa e Editoração: Allyson Vila Nova, Rafael Lira, Italo Amorim e Gláucia Fagundes
Revisão Ortográfica: Marcelo Melo
Ilustrações: Allyson Vila Nova
Coordenação de Produção: Marizete Silva Santos
Sumário

   Apresentação................................................................................................................. 4

   Conhecendo o Volume 1 ................................................................................................ 5

   Capítulo 1 – Introdução a Orientação a Objetos ............................................................. 7

       1. Introdução ...................................................................................................................7

       2. Evolução das Linguagens de Programação ..................................................................8

       3. Paradigmas de Programação .....................................................................................10

   Capítulo 2 – Orientação a Objetos: conceitos principais ............................................... 22

       1. Introdução .................................................................................................................22

       2. Abstração ...................................................................................................................23

   Capítulo 3 – A Linguagem Java ..................................................................................... 37

       1. Introdução .................................................................................................................37

       2. Características da Linguagem ....................................................................................38

       3. Máquina Virtual Java: o alcance de portabilidade .....................................................39

       4. Codificando um primeiro programa Java ...................................................................40

       5. JSDK – Java Software Development Kit ......................................................................42

       6. JCreator: Ambiente de programação de iniciantes ....................................................44

   Conheça o Autor .......................................................................................................... 50
Apresentação
        Caro(a) Cursista,
         Seja bem-vindo(a) ao curso de Programação II. Este curso é composto por 4 volumes. Neste primeiro
volume, vamos estudar a teoria e os principais conceitos relacionados ao paradigma de programação baseado
em objetos. Além de apresentar suas vantagens em relação a outros paradigmas de programação, será também
apresentada a linguagem de programação Java, a ser utilizada no curso para atividades práticas, como exemplos e
exercícios.
         O segundo volume é dedicado em sua totalidade à sintaxe Java, seu sistema de tipos, operadores lógicos,
comandos de decisão e repetição. No terceiro volume você aprenderá a utilizar os conceitos de orientação a objetos
utilizando a sintaxe apresentada no volume anterior.
        Por fim, no quarto e último volume serão abordados assuntos ainda mais avançados, como a ideia de
herança, polimorfismo e tratamento de exceções.
        Bons estudos!
                                                     Fernando Trinta
                                                     Professor Autor




4
Programação II




Conhecendo o Volume 1
         Neste primeiro volume, você irá encontrar o Módulo 1 da disciplina Programação II.
Para facilitar seus estudos, veja a organização deste primeiro módulo.

        Módulo 1 - Uma Introdução ao Paradigma Orientado a Objetos

        Carga Horária do Módulo 1: 15 h
          Objetivo do Módulo 1: Introduzir o paradigma de programação orientada a
objetos, a partir de um histórico evolutivo dos paradigmas de programação, ressaltando
seus benefícios em relação aos demais. Apresentar os principais conceitos do paradigma
orientado a objetos. Introduzir a linguagem de programação orientada a objetos Java, que
será utilizada no curso para utilização prática da teoria explanada.
        Conteúdo Programático do Módulo 1

    »   Introdução (Evolução dos paradigmas computacionais. O problema da
        complexidade. A ideia da abstração. Uma nova forma de encarar o problema:
        Objetos. Vantagens.)
    »   Conceitos Fundamentais do Paradigma OO (Objetos. Classes. Métodos. Atributos.
        Mensagens. Polimorfismo. Herança.)
    »   A linguagem de Programação Java (Histórico. Estrutura do código em Java.
        Compilação. Execução. O método main(). Escrevendo na tela. Independência de
        Plataforma/Máquina Virtual. Ambientes de programação.




                                                                                                          5
Programação II




                              Capítulo 1


                         O que vamos estudar neste capítulo?

                         Neste capítulo, vamos estudar os seguintes temas:

                     »   Introdução ao Paradigma Orientado a Objetos.
                     »   Evolução dos paradigmas computacionais.
                     »   O problema da complexidade.
                     »   A ideia da abstração.
                     »   Uma nova forma de encarar o problema: Objetos.
                     »   Vantagens e Desvantagens do Paradigma Orientado a Objetos.

                         Metas

                         Após o estudo deste capítulo, esperamos que você consiga:

                     »   Identificar as principais características do paradigma de programação orientado a
                         objetos.
                     »   Descrever as vantagens do paradigma orientado a objetos em relação aos demais
                         paradigmas.




6
Programação II




Capítulo 1 – Introdução a Orientação a
Objetos


             Vamos conversar sobre o assunto?


         Caro(a) Cursista, é indiscutível o papel que a tecnologia da informação tem hoje
na sociedade moderna. Praticamente toda a economia mundial está fortemente ligada a
sistemas computacionais que gerenciam bancos, sistemas comerciais, órgãos públicos,
dentre outros. Você alguma vez parou para pensar em como estes sistemas foram e
continuam sendo construídos?! Não?! Então é hora de você começar a refletir sobre como
se dá o processo de construção dos programas que realizam boa parte dos complexos
sistemas computacionais modernos. E para isto, nós vamos abordar neste volume um pouco
sobre o modelo de programação mais difundido atualmente, o paradigma baseado em
objetos. Vamos lá?




1. Introdução
         Nas últimas décadas, a sociedade moderna vem cada vez mais sendo influenciada
por sistemas de informação baseados em computador. Desde sistemas de comércio
eletrônico, passando por jogos de computador e chegando até complexos sistemas militares,
o mundo moderno é cada vez mais refém da tecnologia e dos sistemas de informação. Você
consegue se imaginar em um mundo hoje sem computadores? Sem Internet? É difícil de
imaginar. Este parece ser um caminho sem volta que fica ainda mais visível ao passo que nos
últimos anos têm crescido o uso de aplicações em dispositivos móveis, como celulares, uso
de novas aplicações baseadas em tecnologias inovadoras, como GPS, dentre outros.
         É inegável que as possibilidades do uso de novas tecnologias são importantes
facilitadores para a vida moderna, como no caso de você querer utilizar o seu celular para,
baseado na sua atual localização, descobrir qual a farmácia mais próxima ou o melhor
caminho para chegar a determinado lugar. Porém, do ponto de vista de quem constrói os
novos sistemas, isso tem se tornado um pesadelo, uma vez aumenta a complexidade destas
aplicações.
        Construir as aplicações atuais requer uma série de passos que ajudem a tratar
a complexidade destes sistemas. Estes passos e as pessoas que são envolvidas no
desenvolvimento de sistemas criaram uma disciplina, conhecida hoje como Engenharia
de Software. Esta disciplina ou processo de desenvolvimento concentra as atividades de
entender o que um sistema deve fazer (análise), propor uma solução computacional
(projeto) e desenvolver esta solução (implementar/codificar) (Figura 1). Esta última fase
está diretamente relacionada ao tema desta disciplina: criar aplicações a partir de uma
linguagem de programação.




                Figura 1 – Processo Resumido de Desenvolvimento de Aplicações


                                                                                                          7
Programação II



                             A ideia de codificar representa uma forma de escrever por meio de uma linguagem
                     de programação, o projeto da solução proposta nas fases anteriores da engenharia de
                     software. Informalmente, uma linguagem de programação pode ser definida como um
                     conjunto limitado de instruções (vocabulário), associado a um conjunto de regras (sintaxe)
                     que define como as instruções podem ser associadas. Ou seja, como se pode compor os
                     programas para a resolução de um determinado problema.
                             Os programas escritos em uma linguagem de programação são então traduzidos
                     para uma linguagem de máquina, que é compreendida pelo computador. O resultado desta
                     conversão são programas executáveis que realizam uma série de ações, como solicitar
                     dados, realizar cálculos específicos ou apresentar dados para usuários.
                               Ao longo dos anos, foram desenvolvidas (e continuam sendo) uma grande
                     quantidade de linguagens de programação, algumas de uso mais geral e outras concebidas
                     para áreas de aplicação específicas. Porém, apesar de suas diferenças, estas linguagens são
                     geralmente agrupadas de acordo com as características principais que indicam como um
                     programador (quem escreve o programa) enxerga a forma de organizar os programas. As
                     diferentes maneiras como uma linguagem organiza seus conceitos é chamada de paradigma
                     de programação. Dentre alguns dos mais conhecidos paradigmas de programação podem-
                     se citar: paradigma imperativo, paradigma estruturado e o paradigma orientado a objetos.
                     A tabela a seguir indica o índice de popularidade dos principais paradigmas de programação
                     existentes:


                                  Tabela 1 – Distribuição de Paradigmas segundo índice de popularidade
                                [Fonte: http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html]

                                                Paradigma             Indice de Popularidade

                                            Orientado a Objetos               54,6%

                                                Procedural                    41,5%

                                                 Funcional                     2,8%

                                                  Lógico                       1,1%

                             Neste momento, caro(a) cursista, você pode se perguntar: para que diferentes
                     paradigmas? Para responder esta questão é necessário voltar no tempo e entender como as
                     linguagens de programação evoluíram ao longo dos anos.



                     2. Evolução das Linguagens de Programação

                     2.1. A linguagem de máquina e a linguagem montadora

                              Um computador é organizado em um conjunto de circuitos eletrônicos. Desta
                     forma, seu controle é feito ainda através de uma forma bem primitiva, baseado em um
                     sistema binário para representação de dados e operações. Esta representação é chamada
                     de código binário ou linguagem de máquina, por ser compreendida e executada no
                     hardware do computador. Esta linguagem consiste de uma grande sequência de números
                     (1s e 0s), que instruem os computadores a realizar suas operações mais elementares, uma
                     de cada vez. A figura a seguir apresenta um trecho de um possível programa em linguagem
                     de máquina.




8
Programação II




                               Figura 2 – Código de Máquina



        Criar programas em código binário é impraticável. Para facilitar a construção
dos programas, uma nova linguagem de programação foi proposta, onde eram utilizadas
abreviações para representar as operações elementares. As linguagens que seguiram esta
estratégia foram chamadas linguagens montadoras ou assembly. Em Assembly, em vez
de números binários, utiliza-se palavras abreviadas, chamadas também de mnemônicos,
indicando a operação a ser realizada. Estas linguagens estavam mais próximas do
entendimento dos humanos, e através de um programa chamado montador, o código
binário era gerado e podia a ser executado nos computadores da época. Abaixo são
apresentados dois exemplos de instruções Assembly:

    »   MOV R1, R2 – A instrução MOV (abreviatura do termo em inglês MOVE) recebe
        como parâmetros, dois registradores: R1 e R2. Sua execução determina a cópia do
        conteúdo de R2 para R1 (equivalente R1:=R2, sendo R1 e R2 equivalente a duas
        variáveis);
    »   ADD R1, R2 – A instrução ADD (abreviatura de ADDITION) recebe como parâmetro,
        dois registradores como parâmetros: R1 e R2. Sua execução adiciona o conteúdo
        de R1 ao de R2 e o resultado é armazenado em R1 (equivalente à instrução Pascal
        R1:=R1+R2).
         Utilizando estes comandos, os programadores utilizaram Assembly para realizar
seus programas. Por exemplo, para somar dois inteiros, um programa em Assembly poderia
ser escrito através da rotina descrita abaixo.

 MOV AX,B ; registro AX recebe o valor de memória contida na variável B

 ADD AX,C ; AX recebe a soma de AX (valor de B) com o valor de C

 MOV A,AX ; variável A recebe valor de AX

          Dá para verificar que o mesmo ainda está bem próximo da linguagem da máquina
que do homem. Difícil de entender!? Bastante! Porém, isso na época permitiu que se
facilitasse a forma de se construir os programas de computador.


2.2. Aumentando o nível de abstração das linguagens

         O uso dos computadores foi se popularizando. Com isso, novas aplicações foram
propostas para os computadores que surgiram. Com isso, tornou-se necessário facilitar
ainda mais a forma como os programas de computadores eram escritos. Surgiram então as
chamadas linguagens de programação de alto nível, onde uma única instrução poderia ser
utilizada para realizar várias operações elementares do computador. Um programa tradutor
chamado compilador transformava o código em alto nível em linguagem de máquina.
Programas passaram a ser escritos em uma linguagem mais próxima da linguagem natural e
utilizavam notações matemáticas semelhantes ao cotidiano das pessoas. Um programa para
calcular o fatorial de um número poderia ser escrito como na figura a seguir.




                                                                                                       9
Programação II



                       int fatorial(int n)

                       {

                           if (n == 0)

                                 return 1;

                           else{

                                 fat = 1;

                                 for (int i=2:i<=n){

                                           fat = fat * i;

                                 }

                                 return fat;

                           }

                       }

                               Figura 3 – Trecho de um programa para cálculo de um fatorial escrito na linguagem C



                               Se mesmo para você esta versão em uma linguagem de alto nível ainda seja
                      incompreensível, pelo menos se percebe que são utilizados menos construções para se
                      realizar a mesma tarefa que em uma linguagem montadora. Desta forma, os programas
                      ficaram mais fáceis de serem compreendidos por nós, humanos. Isto facilitou bastante a
                      programação e, principalmente, a manutenção e correção de erros nos programas. Várias
                      foram as linguagens de alto nível propostas. Dentre algumas, pode-se citar Fortran, Pascal,
                      Basic e C. Algumas delas são bem populares ainda hoje.
                              O surgimento das linguagens de alto nível auxiliou programadores a construir
                      programas mais enxutos, mas fáceis de compreender e também de corrigir erros... Mas
                      onde está o conceito de paradigma nesta história?! Vamos lá então...



                      3. Paradigmas de Programação

                      3.1. Paradigma Imperativo

                               Como vimos anteriormente, um paradigma de programação explica como
                      elementos que compõem um programa são organizados e interagem entre si. No caso
                      das linguagens montadoras ou das linguagens de alto nível, a construção dos programas é
                      realizada através de instruções que indicam o que o computador deve realizar. A diferença
                      é que para linguagens montadoras, o programador precisava ser muito mais detalhista que
                      em uma linguagem de alto nível. Um simples comando na linguagem C era equivalente
                      a dezenas de linhas em uma linguagem de baixo nível. Porém, a ideia era a mesma: um
                      conjunto de instruções que ilustram uma estratégia de um ser humano em “COMO” resolver
                      um problema.
                              Esta forma de organizar os programas estabelece um primeiro paradigma de
                      programação conhecido: o paradigma imperativo. Programar um computador neste
                      paradigma significa “dar-lhe ordens” que são executadas sequencialmente. O paradigma
                      imperativo é profundamente influenciado pela arquitetura como os próprios computadores
                      são organizados, a arquitetura de von Neumann. Neste modelo, você deve pensar em um
                      programa como um computador que tem memória que guarda um estado por meio de


10
Programação II



dados (variáveis), e que recebe instruções que modificam e apresentam estes dados, como
ilustrado na figura a seguir:




                        Figura 4 – Modelo Imperativo de programação



        Como todas as arquiteturas de computadores existentes hoje se baseiam na
arquitetura de Von Neumann, os ambientes de execução das linguagens imperativas são
bastante eficientes.
         Porém, mesmo assim, programas escritos no paradigma imperativo ainda são
muito detalhistas, o que requer um grande esforço na construção e, principalmente,
na manutenção dos programas. Conforme a complexidade dos programas aumenta, a
legibilidade, ou seja, a facilidade com que os programas podem ser lidos e entendidos,
torna-se também mais difícil. Com isso, a manutenção continuou sendo um problema, e
erros acabavam sendo introduzidos sem querer durante o processo de depuração (correção)
de programas.


3.2. Paradigma Procedural

         Uma evolução do paradigma imperativo foi a percepção que certas sequencias de
instruções que são repetidas em vários pontos de um mesmo programa. Estes sequências de
passos poderiam ser agrupadas em procedimentos e funções (também chamados de sub-
rotinas) definidas pelo programador e serem chamadas de diversos pontos do programa,
como no caso de criarmos uma função que calcule o valor do fatorial de número (Figura 5).
Por esta característica, o paradigma imperativo também é conhecido na literatura como o
paradigma procedural.




                   Figura 5 – Paradigma Imperativo VS Paradigma Procedural




         O paradigma procedural foi durante muitos anos o padrão para linguagens de
programação. Este paradigma acabou influenciando também a forma como a própria análise
e projeto das aplicações eram realizados. O paradigma procedural induzia que sistemas
mais complexos precisavam ser “quebrados” em partes menores, mas fáceis de lidar. Este
princípio de “dividir para conquistar” é a abordagem padrão que os desenvolvedores de
sistemas utilizam para lidar com sistemas complexos.
       No caso do paradigma procedural, o sistema era dividido em muitas funções
que representavam as diversas funcionalidades que o programa tinha que fazer. Isso era

                                                                                                        11
Programação II



                      repetido até se chegar a um nível que as funções eram claras o suficiente para entender
                      seu funcionamento, ou mesmo para serem reaproveitadas em diferentes pontos de um
                      programa. Com procedimentos, funções menores eram mais fáceis de entender, além de
                      facilitar eventuais correções de um programa, em caso de erros.
                               De certa forma, esta abordagem de lidar com a complexidade também lida com um
                      conceito chave para a construção de sistemas e a programação de aplicações: a abstração.
                      A ideia de abstração faz com que os desenvolvedores concentrem seus esforços no que é
                      relevante, deixando detalhes irrelevantes para serem tratados mais tarde. Abstração dentro
                      de um paradigma de programação indica como os problemas são encarados. Os conceitos
                      utilizados para resolver estes problemas são as abstrações utilizadas por um paradigma.
                      No caso do paradigma procedural, as abstrações utilizadas para decompor um problema
                      complexo são as sub-rotinas (funções e/ou procedimentos).
                               O uso de sub-rotinas separa dados (variáveis) e operações (procedimentos) sobre
                      os dados, onde a ideia de funções e procedimentos manipulando um conjunto de dados
                      surgiu como um modelo natural para representar como as aplicações.
                              Porém, esta abordagem também apresenta seus problemas. Primeiro, o caminho de
                      execução do programa ficou mais complexo devido à chamada de funções e procedimentos
                      em diversas partes do código. A confusão de chamadas e desvios era tão grande que se
                      criou um termo específico para os programas mal-estruturados a partir de várias chamadas
                      de sub-rotinas, o “código espaguete” (Figura 6).




                                                       Figura 6 – O código espaguete
                                   [Fonte: http://www.yourdictionary.com/images/computer/SPAGETI.GIF]



                               No entanto, o maior problema está relacionado com a separação de dados e
                      procedimentos, pois várias partes de um mesmo programa podiam alterar os valores de
                      variáveis compartilhadas. Em muitos casos, a modificação de uma variável por uma sub-rotina
                      causava a falha na execução de outra sub-rotina que dependia do valor da mesma variável.


12
Programação II



Além disso, como procedimentos utilizavam valores em variáveis separadas, uma alteração
na representação de uma variável poderia exigir uma alteração em cascata em todas as sub-
rotinas que dependessem deste valor. Ou seja, um pesadelo para o programador!




            Figura 7 – Relação entre dados e procedimentos no paradigma procedural



        Vejamos isso em exemplo mais claro, como o cálculo de uma folha de pagamento
de uma empresa. Neste caso, os dados relativos a cada um dos funcionários ficariam
espalhados no programa. Seria necessário recuperar estes dados para cada funcionário
obter e então realizar o processamento do cálculo da folha de pagamento (Figura 8). Este
processamento seria representado por uma função ou uma sub-rotina.




             Figura 8 – Cálculo de uma folha de pagamento no paradigma procedural



         Com o aumento da complexidade das aplicações, o gerenciamento entre
procedimentos e dados dispersos criava um pesadelo para os programadores que precisavam
realizar manutenções no sistema. Modificações em um dado poderiam desencadear um
processo de atualização em vários procedimentos.




   Figura 9 – Dificuldade do gerenciamento de dados e procedimentos no paradigma procedural



        Além disso, verificou-se que ao longo dos anos, os procedimentos mudavam muito
mais que os dados manipulados. Como exemplo, as regras que podem ser associadas ao
cálculo do salário de um funcionário variam muito mais que os dados do funcionário,
como seu nome ou seu cargo. Desta forma, era necessária uma nova forma de organizar os
sistemas.


                                                                                                               13
Programação II



                      3.3 Programação Modular e Estruturada

                              Para tentar melhorar as deficiências do paradigma procedural, surgiu
                      então a programação modular. Nesta abordagem, o programa é dividido em vários
                      componentes ou módulos. Ao contrário do paradigma procedural, módulos combinam
                      dados e procedimentos. Um módulo é composto de dados que são manipulados pelos
                      procedimentos deste módulo. Cada módulo fornece um conjunto de procedimentos para
                      que outras partes de um programa possam acessar dados internos de um módulo. Este
                      conjunto de procedimentos ou funções é conhecido como interface do módulo. Desta
                      forma, dados internos de um módulo são protegidos contra manipulações indevidas de
                      outros módulos, em um princípio conhecido como encapsulamento.
                              Estas características trouxeram vantagens em relação aos seus predecessores.
                      Dentre algumas, pode-se citar:

                          »   Estrutura do programa fica mais clara ao agrupar funções e variáveis relacionadas
                              em um mesmo módulo;
                          »   Possibilidade de alterar módulos separadamente. Uma vez que cada módulo
                              preserve sua interface visualizada por outros módulos, modificações internas e
                              novos procedimentos podem ser incluídos;
                          »   O acesso a dados internos de um módulo é feito através de sua interface. Com
                              isso, tem-se um maior controle sobre operações indevidas sobre estes dados. Por
                              exemplo, é possível verificar se um dado pode ou não ser modificado para um
                              determinado valor, antes de se efetivar a mudança.
                              Este estilo de programação também muito referenciada como programação
                      estruturada, devido a uma melhor organização dos conceitos utilizados nos programas.
                      A programação estruturada tornou-se um sucesso e, a partir de seus conceitos, métodos
                      de modelagem e análise foram propostos para facilitar o projeto das novas aplicações que
                      surgiam na época em que surgiu a programação estruturada, como a Análise Estruturada de
                      Tom DeMarco, e a Análise Estruturada Moderna, de Edward Yourdon.
                                Com as ideias de módulos, encapsulamento e interfaces, a programação modular
                      permitiu um melhor aproveitamento e distribuição de programas. Os módulos construídos
                      por um programador poderiam ser reaproveitados por outros programadores, sem a
                      necessidade de se entregar código-fonte. Bastava que os programadores que desejassem
                      utilizar um módulo soubesse a interface deste módulo. Imagine um módulo como uma
                      biblioteca de funções. Poderia haver um módulo para fazer, por exemplo, a verificação se
                      um CPF é válido ou não. A única coisa que um programador precisaria saber é que este
                      módulo possui uma função chamada valida_cpf, que recebe como parâmetro um número
                      de 11 dígitos e retorna verdadeiro se este número representa um CPF válido. Para os
                      programadores que vão utilizar o módulo, ele é considerado uma caixa-preta, no sentido
                      que não se sabe como ele funciona internamente. O importante é que ele forneça o
                      resultado que se espera dele.
                               Porém, a programação modular também apresenta seus problemas. O primeiro
                      e principal problema é o fato que módulos não eram naturalmente extensíveis. Isso
                      significava que para fazer alterações em módulo, era necessário entrar no código-fonte e
                      diretamente realizar as modificações. E em muitas situações, se via a necessidade de criar
                      novas funcionalidades dos programas a partir de módulos já existentes.




14
Programação II



3.4. O Paradigma Orientado a Objetos

                                  O termo “programação orientada a objetos” foi criado
                          por Alan Kay (imagem ao lado), autor da linguagem Smalltalk.
                          Sua proposta visa aproximar a maneira como construímos os
                          programas de computador do mundo real.
                                   O mundo real é composto por entidades que interagem,
                          que trocam serviços entre si para realizar suas tarefas. Na
                          proposta de orientação a objetos, estas entidades são chamadas
                          objetos.


        Objetos podem representar tanto entidades concretas (como uma pessoa ou
um livro) quanto entidades abstratas (como uma transação bancária ou uma sessão de
um usuário ao acessar um site). Para identificar objetos são empregadas técnicas que os
próprios seres humanos utilizam para organizar seus pensamentos, como classificação de
elementos, diferenciação entre parte e todo, troca de mensagens, dentre outros.
        Alan Kay utilizou uma analogia com um sistema molecular, batizada então de
“analogia biológica”. Nesta proposta, ele se questionou: “como seria um sistema de
computador que se organizasse como um ser vivo?”. Sua proposta estabelecia que:

    »   O sistema seria organizado em células, onde cada célula se comportaria como uma
        unidade autônoma;
    »   Cada “célula” interagiria com outras células através do envio de mensagens para
        realizar um objetivo comum;
         Para Kay, objetos do mundo real também se comportam como estas células. A
partir de sua analogia biológica, ele estabeleceu os princípios básicos para a orientação a
objetos. São estes:

    1. Qualquer coisa é um objeto;
    2. Objetos realizam tarefas através da requisição de serviços a outros objetos;
    3. Cada objeto pertence a uma determinada classe. Uma classe agrupa objetos
       similares;
    4. A classe é um repositório para comportamento associado ao objeto;
    5. Classes são organizadas em hierarquias.

        3.4.1. Estabelecendo um exemplo

        Para melhorar sua compreensão, vamos utilizar um exemplo prático. Imagine
a situação em que um cliente chamado Ian deseja comprar uma pizza via um serviço de
entrega em domicílio. Ian interage com uma atendente (Maria) e faz sua solicitação.
Maria por sua vez interage com Mário, o pizzaiolo, repassando a solicitação de Ian, uma
vez que quem sabe fazer a pizza é Mário, afinal ele é o pizzaiolo. Após a pizza ficar pronta,
ela é entregue ao Zé, o motoboy, que tem por função entregar a pizza a Ian e receber o
pagamento. A Figura 10 ilustra a interação entre estes personagens.




                                                                                                            15
Programação II




                                       Figura 10 – Um exemplo para a orientação a objetos na vida real



                               Embora o exemplo acima ainda possa ser refinado e inserir ainda mais participantes,
                      ele é suficiente para ilustrar os conceitos propostos pelo paradigma orientado a objetos.
                      Primeiramente, cada elemento que participa do processo é considerado um objeto. Cada
                      objeto é uma entidade única no sistema. No caso temos Ian, Maria, Mário e Zé como
                      objetos. Não existem duas “Marias”. Poderiam até existir duas funcionárias com o mesmo
                      nome, mas não seriam a mesma pessoa. Cada objeto tem dados ou propriedades que os
                      identificam. No caso, cada pessoa no processo tem um nome.
                               Cada objeto interage com os demais por meio da solicitação de serviços. No caso,
                      Ian solicita seu pedido através da atendente Maria, que lhe fornece os produtos que ela
                      pode entregar a Ian. De forma semelhante, Maria solicita a Mário a pizza escolhida por Ian,
                      passando informações necessárias para realização deste serviço, como o sabor da pizza e o
                      tipo da borda, como ilustrado na Figura 11.




                              Figura 11 – Solicitação de um serviço através da troca de mensagem entre objetos



                               Seguindo sua análise, cada objeto pertence a uma determinada classe que agrupa
                      objetos similares. No nosso exemplo, a pizzaria não atende apenas ao cliente Ian. Podem
                      existir outras dezenas de clientes que também podem fazer seus pedidos à Pizzaria. Estes
                      clientes possuem características comuns, como um cadastro na loja ou um endereço de

16
Programação II


entrega. Obviamente, para cada cliente, os valores associados a estas propriedades são, em
geral, diferentes. Estes objetos são tratados e agrupados como um tipo único de objeto,
uma classe. Neste caso, poderíamos agrupar Ian, Cris e Evandro como objetos da classe
Cliente, como ilustrado na Figura 12.




                          Figura 12 – Objetos de uma mesma classe



         Por fim, classes são organizadas em hierarquias. No nosso exemplo, Maria, Mário
e Zé poderiam ser agrupados em uma classe que representem os funcionários da Pizzaria
(Figura 13). Estes possuem características comuns como um salário, um horário de trabalho.
Porém, estes também poderiam ser classificados como pessoas, com atributos como nome,
sexo, dentre outros. Neste caso, a classe Pessoa englobaria tanto funcionários quanto
clientes, indicando que existem certas propriedades comuns, como o fato de tanto clientes
quanto funcionários possuírem um nome.




                         Figura 13 – Hierarquias de classes de objetos



        Mas vistos estes conceitos, em que a orientação a objetos pode melhorar a forma
como programamos nossas aplicações? Para isso, vamos pegar o exemplo do cálculo de
uma folha de pagamento de uma empresa, como ilustrado na Figura 14.




                  Figura 14 – Uma folha de pagamento no modelo estruturado

                                                                                                         17
Programação II



                              Relembrando: como os dados e funções são separados, calcular o custo total da
                      folha requer que saibamos individualmente todos os dados de cada funcionário, o que
                      acabava por fazer com que a evolução do sistema ficasse bastante complicada. Agora veja
                      como seria uma possível versão utilizando a abordagem orientada a objetos (Figura 15).




                                         Figura 15 – Uma folha de pagamento no modelo de objetos



                               Nesta versão, cada funcionário é representado por um objeto. Um objeto atua
                      como um módulo que engloba dados, e também fornece operações que manipulam tais
                      dados. Os dados internos de cada objeto são chamados atributos, enquanto as operações
                      que um objeto fornece são chamados de métodos. No caso, todo objeto que representa
                      um funcionário possui como atributos seu nome, seu cargo, seu salário fixo e uma série
                      de outros atributos que são comuns a qualquer funcionário da empresa. Para se calcular
                      seu salário, cada funcionário oferece um método chamado calculaSalario, que internamente
                      utiliza os dados de cada objeto e fornece o valor de seu salário individual. Para calcular o
                      custo total da folha de pagamento seria então somar os valores obtidos pela chamada de
                      cada método calculaSalario, em cada objeto que representa um funcionário da empresa.
                              A orientação a objetos representa uma nova forma de enxergar e modelar o
                      mundo como um conjunto de objetos inter-relacionados, interagindo por meio da troca de
                      mensagens. A abstração escolhida (objeto) combina estrutura de dados e comportamento
                      funcional, fazendo com que os dados sejam preservados e procedimentos modificados
                      mais facilmente, sem causar impactos tão profundos quanto o paradigma estruturado. A
                      ocorrência de erros ou alterações vão estar associadas a um único módulo ou a um pequeno
                      grupo deles, onde é mais fácil depurar e isolar erros.
                               Esta forma de organizar os programas cria um modelo mais intuitivo e fácil
                      de usar, mas principalmente, aumenta a possibilidade de reuso entre objetos. Objetos
                      podem ser criados a partir de outros objetos. Por exemplo, você poderia criar um objeto
                      que representasse um funcionário diferenciado, como aquele cujo salário fosse baseado
                      em comissões, e não em um salário fixo. Este objeto poderia ser criado através de um
                      mecanismo especial de extensão chamado Herança. Resumidamente, este novo objeto
                      teria as mesmas características de um funcionário comum, mas poderia ter dados a mais,
                      assim como seus métodos poderiam ser modificados, como no caso de seu salário.


                      3.5. Programação Orientada a Objetos VS Programação
                      Estruturada

                              A forma de organizar um programa usando orientação a objetos é essencialmente
                      diferente do desenvolvimento tradicional de software. Mesmo assim, alguns conceitos do
                      modelo orientado a objetos podem ser equiparados a conceitos do modelo estruturado,


18
Programação II



como visto na figura a seguir.




               Figura 16 – Paradigma orientado a objeto VS Paradigma Estruturado



          A programação orientada a objetos é especialmente útil à medida que os sistemas
tornam-se cada vez mais complexos, e por consequência, seus programas ficam cada
vez maiores. Grandes programas se beneficiam mais com a modularidade oferecida por
objetos. Dividindo o programa em vários módulos independentes (objetos), aumenta-se a
flexibilidade e a facilidade para manutenção do programa como um todo.
         Na programação estruturada, a reusabilidade é limitada a trechos de algoritmos
representados por meio de sub-rotinas. Na programação orientada a objeto é possível
reutilizar todo um módulo, no caso o objeto, com seus métodos e seus atributos. Em geral,
a programação orientada a objetos ainda apresenta como vantagens: código mais lógico,
e melhor encapsulado, uma maior facilidade de manutenção e extensão do código, um
melhor reaproveitamento de código, dentre outros.
         Como desvantagens, pode-se afirmar que o aprendizado de uma linguagem
orientada a objetos é mais complexo, principalmente para aqueles já familiarizados com o
paradigma estruturado. É necessário mudar a forma de pensar na solução de um programa,
utilizando conceitos não tão simples quanto do paradigma estruturado. Por fim, dificilmente
uma linguagem orientada a objetos conseguirá ter um desempenho em tempo de execução
superior a linguagens não orientadas a objetos.


              Exercícios


    1. Com suas palavras conceitue: (a) linguagem de programação e (b) paradigma de
       programação.
    2. Utilizando a Internet, verifique quais são os outros paradigmas de programação
       existentes além dos apresentados neste capítulo. Explique qual o propósito de pelo
       menos dois outros paradigmas.
    3. Em sua opinião, ainda faz sentido hoje se programar em uma linguagem de baixo
       nível como Assembly?! Justifique sua resposta.
    4. Para muitos pesquisadores, o paradigma orientado a objetos é apenas uma
       extensão do paradigma estruturado. Você concorda ou discorda desta opinião?
       Justifique.
    5. Utilizando a abordagem de uma programação estruturada, resolva o seguinte
       problema. É necessário descobrir o atleta que mais marcou gols em um campeonato
       de futebol. Descreva (em português ou em linguagem de programação que você
       conheça) como seria solução deste problema.
    6. Utilizando o mesmo problema da questão anterior, como seria a solução utilizando


                                                                                                          19
Programação II



                              objetos.




                                     Minibiografia




                        Edsger Wybe Dijkstra (11 de Maio de 1930 — 6 de Agosto de 2002) foi um pesquisador holandês
                        mundialmente conhecido por suas contribuições nas áreas de desenvolvimento de algoritmos e
                        programas de linguagens de programação. Foi o precursor da ideia contrária ao uso de comandos
                        “GOTO” em linguagens de programação, um recurso muito utilizado na sua época. Em seu artigo
                        “A Case against the GO TO Statement”, Dijkstra alertou para vários erros decorrentes do uso da
                        declaração GOTO. Uma transcrição deste artigo pode ser visto na URL: http://www.cs.utexas.
                        edu/~EWD/transcriptions/EWD02xx/EWD215.html. Suas pesquisas impulsionaram o surgimento
                        da programação estruturada.Em 1972, recebeu o Prêmio Turing por suas contribuições com o
                        ALGOL e no campo de linguagens de programação.




                                   Vamos Revisar?


                               Você estudou, neste capítulo, como as linguagens de programação evoluíram ao
                      longo dos anos no intuito de facilitar a vida dos programadores das aplicações modernas.
                      Esta evolução foi motivada principalmente pela crescente complexidade dos programas.
                      Com isso, as linguagens têm focado principalmente em criar abstrações que melhorem a
                      compreensão e manutenção destes programas. Você também viu que é possível classificar
                      as linguagens em grupos que seguem o mesmo conjunto de ideias sobre a estruturação e
                      execução de um programa, os chamados paradigmas de programação. Desde o paradigma
                      imperativo até o paradigma estruturado, vários foram os avanços na estruturação dos
                      programas, como a reutilização através de sub-rotinas até o uso de módulos autocontidos
                      que protegem seus dados de acesso indevido. Apesar destas evoluções, havia muito o que
                      evoluir, principalmente no que diz respeito ao reuso dos programas. Para isso, uma nova
                      abordagem de programar foi proposta: a orientação a objetos. Neste novo paradigma,
                      programas se aproximam mais do mundo, através de objetos que interagem para a
                      realização de uma tarefa. No próximo capítulo, você verá com mais detalhes os principais
                      conceitos deste novo paradigma.




20
Programação II




         Capítulo 2


    O que vamos estudar neste capítulo?

    Neste capítulo, vamos estudar os seguintes temas:

»   Conceitos fundamentais do paradigma orientado a objetos, como:
     ›   Classes, Objetos, Atributos e Métodos.
     ›   Abstração.
     ›   Encapsulamento.
     ›   Polimorfismo.
     ›   Herança.

    Metas

    Após o estudo deste capítulo, esperamos que você consiga:

»   Descrever os principais conceitos utilizados no paradigma orientado a objetos.




                                                                                                      21
Programação II




                      Capítulo 2 – Orientação a Objetos:
                      conceitos principais


                                   Vamos conversar sobre o assunto?


                               No capítulo anterior, você viu que ao longo dos anos a programação buscou
                      uma constante evolução no intuito de facilitar a vida dos programadores. O progresso
                      na organização dos programas evoluiu. Porém, os sistemas também ficaram cada vez
                      mais complexos. Em particular, os paradigmas de programação até então falhavam
                      principalmente em relação à reutilização de código. Para enfrentar este problema, um
                      novo paradigma surgiu: a orientação a objetos. Vamos abordar neste capítulo os principais
                      conceitos relacionados a esta nova forma de organizar seus programas. Este capítulo é
                      fundamental para seu bom progresso no curso. Então, vamos aprender?




                      1. Introdução
                              Como vimos no capítulo anterior, a programação orientada a objetos surgiu
                      como uma nova abordagem para tratar a inerente complexidade dos novos sistemas. A
                      programação orientada ao objeto (object-oriented programming) pode ser considerada
                      como uma extensão quase natural da programação modular. Apesar de seus conceitos já
                      terem sido estabelecidos desde a década de 70, apenas em meados da década de 90 que
                      este paradigma começou a ganhar maior destaque na comunidade de desenvolvimento de
                      sistemas.
                               Seu uso enfatizou uma ideia que até então passava despercebida: a aproximação
                      com o mundo real. Na programação orientada a objetos temos a necessidade de buscar
                      as entidades de um domínio, onde através da qual um indivíduo observa a realidade
                      (domínio) e procura capturar sua estrutura (abstrair entidades, ações, relacionamentos)
                      com elementos que forem considerados relevantes para a descrição desse domínio. Com
                      as entidades de domínio identificadas, podemos utilizar as técnicas de abstração para
                      a composição das classes abstratas, construindo desta maneira um sistema facilmente
                      reutilizável nas suas estruturas internas.
                               A abordagem OO (orientada a objetos) enfatiza duas características: (i) reutilização
                      de código e (ii) modularidade. Nisto, OO é imbatível quando comparada com as metodologias
                      antigas. Em termos de modelo computacional podemos dizer que enquanto as metodologias
                      tradicionais utilizam o conceito de um processador, uma memória e dispositivos de I/O para
                      processar, armazenar e exibir as informações. A orientação a objetos emprega um conceito
                      mais real, mais concreto: o de Objeto.
                             Porém, além de objetos, existe uma série de outros conceitos que são
                      importantes para a compreensão do paradigma OO, representados na Figura 17. São eles:
                      encapsulamento, polimorfismo, herança, composição e abstração.




22
Programação II




                     Figura 17 – Os pilares do paradigma orientado a objetos



       Vamos dar uma olhada agora como cada um destes conceitos contribui no
paradigma OO.



2. Abstração
         Abstração é considerada a habilidade de modelar características do mundo real
do problema que o programador esteja tentando resolver. Ao mesmo tempo, para melhor
lidar com a modelagem de problemas complexos, este processo mental indica que se
deve ignorar detalhes não relevantes e focar nas características essenciais dos elementos
modelados. Com isso, uma realidade complexa pode ser representada em um modelo
simplificado, como os objetos no paradigma OO.
         A abstração na descrição de objetos depende do ponto de vista e objetivo de
quem faz a descrição. Grady Booch, um atuante e renomado pesquisador na comunidade
científica, ilustra esta observação na sua frase: “Uma abstração depende mais do observador
do que do objeto observado”. Por exemplo, a visão de um apartamento por um engenheiro
civil tende a ser diferente da de um decorador de ambientes. O primeiro deve se preocupar
mais com os aspectos relacionados ao posicionamento de vigas de sustentação, colunas,
dentre outros. Já um arquiteto se preocuparia mais em como otimizar o espaço, maximizar
a circulação de ar, do melhor local para colocar mesas e cadeiras.
         Estas diferentes visões ocorrem pelo diferente interesse que os dois profissionais
tem sobre a mesma entidade observada: o apartamento. O mesmo vale para a programação,
pois só devemos representar nos sistemas que vamos criar, aquelas características que nos
interessam dos objetos reais. Como exemplo, ao modelarmos um objeto avião no contexto
de um sistema de venda de passagens aéreas, não vai nos interessar a característica do
número de turbinas do avião, mas sim, seu número de assentos disponível.
        Existe uma série de princípios que são utilizados por nós, humanos, para realizar
abstrações em nosso cotidiano. Vamos ver como alguns destes princípios e como eles se
aplicam no paradigma OO.


2.1. Classificação/Instanciação

        Classificação é um mecanismo de abstração através do qual o ser humano percebe
a existência de um conjunto de fenômenos da realidade (elementos, interações) com
algumas características em comum e atribui um nome (conceito) a esse conjunto (classe) de
fenômenos. Já a instanciação é o processo inverso à classificação.
         Na orientação a objetos, este princípio é utilizado para a identificação de classes e
objetos. As duas ações possíveis são:

    »   Classificar significa agrupar objetos com base em estruturas e comportamentos
        semelhantes;


                                                                                                             23
Programação II



                          »   Instanciar objetos significa gerar novos exemplares a partir de uma descrição
                              abstrata de um objeto genérico.
                             Vejamos o exemplo na Figura 18, que ilustra estes processos no contexto de dois
                      estudantes, João e Maria. Ambos são indivíduos, com seus dados particulares, como seus
                      nomes. Porém, ambos podem ser agrupados no conjunto de indivíduos que representam os
                      estudantes.




                                             Figura 18 – Classificação/Instanciação de objetos



                              A “semântica” ou o significado do mecanismo de classificação equivale a um
                      mecanismo de pertinência. Neste mecanismo, o fato de um objeto pertencer a uma
                      determinada classe pode ser melhor caracterizado se ocorrer uma relação do tipo “é um / é
                      uma”. Por exemplo, “Maria é uma estudante”.
                               A partir desta abstração, pode-se então melhor entender os conceitos de objetos e
                      classes, atributos e métodos.
                               Objetos representam entidades do mundo real, quer sejam estas concretas ou
                      abstratas, sobre as quais são armazenados dados e temos operações para manipulá-los.
                      Objetos também se caracterizam por ter uma identidade única, um comportamento e um
                      estado. A identificação de objeto deve ser única, uniforme e independente do conteúdo do
                      objeto. Isso implica que podem haver objetos com características semelhantes (como dois
                      martelos azuis ou dois funcionários com o mesmo nome), mas que são distintos.
                              Uma classe é abstração das características mais importantes de um grupo de
                      objetos semelhantes. Cada classe descreve um conjunto (possivelmente infinito) de objetos
                      individuais. A partir de uma classe podem ser gerados diferentes objetos e por isso, cada
                      objeto é dito ser uma instância de uma classe. Assim, cada instância de uma classe tem seus
                      próprios valores para cada dado que o caracteriza, mas também podem compartilhar dados
                      e comportamento com as outras instâncias da classe. Implicitamente, cada objeto contém
                      uma referência para sua própria classe -- em outras palavras, ele sabe o que ele é.
                                Existe hoje uma representação bastante difundida para representar graficamente
                      classes em um modelo orientado a objetos. Esta notação é definida por uma linguagem visual
                      chamada UML (do inglês, Unified Modeling Language). UML é utilizada para representação
                      de muitas etapas durante a análise de um sistema. Ela é formada por vários diagramas.
                      Um deles é o diagrama de classes, em que classes são representadas graficamente. Para
                      facilitar nossa explicação sobre os conceitos OO, utilizaremos a notação UML para descrever
                      as classes nesta disciplina. Em UML, uma classe é representada como descrito na figura a
                      seguir.




24
Programação II




                             Figura 19 – Notação UML para Classes



         Nesta notação, há uma caixa retangular composta de três partes. A primeira parte
(localizada no topo do retângulo) define o nome da classe. Esta é única parte que deve existir
na notação UML para representar uma classe. A parte intermediária diz qual é a estrutura
da classe. Enquanto a parte inferior informa qual é o seu comportamento, através das ações
que objetos desta classe podem realizar. Para melhor exemplificar, a classe Estudante tem
como estrutura interna o nome do estudante e o curso ao qual ele está vinculado. Como
ações, é possível pedir para um objeto imprimir seu nome.
        Cada objeto possui um conjunto de características ou informações que os
caracteriza, chamadas então de atributos. O conjunto de atributos também é chamado
de estrutura da classe. Por exemplo, a classe Estudante pode conter como sua estrutura
informações como o nome, sexo, data de nascimento, colégio ou faculdade, dentre outros.
Os atributos possuem valores, funcionando como variáveis. Por exemplo, o atributo nome
para um dos objetos da Figura 19 deve guardar o valor “João”. O conjunto de valores dos
atributos de um determinado objeto é chamado de estado. Como visto na Figura 19,
atributos (se existirem) são representados na parte intermediária de uma classe em UML.
          O comportamento de um objeto é definido através de seus métodos. Métodos
definem as habilidades dos objetos. Em outras palavras, as ações que um objeto de uma
classe pode realizar. É comum serem chamados também de comportamento de uma classe
de objetos. Na maioria das vezes, métodos utilizam os atributos da classe como “matéria-
prima” para realizar suas ações, além de também poderem receber parâmetros, como em
um procedimento tradicional. Uma classe pode ter qualquer número de métodos, inclusive
nenhum. Por exemplo, para uma classe carro, poderiam ser definidas ações como andar,
frear, ligar o motor, dentre outras. Como visto na Figura 19, métodos (se existirem) são
representados na parte inferior de uma classe em UML.
         Métodos são definidos nas classes, porém sua execução só ocorre quando o
método é invocado através do objeto. Por exemplo, pode haver uma classe que represente
um automóvel e dois objetos que representem dois modelos diferentes: um Fusca e uma
Ferrari. A classe define um método, que faz com que a velocidade do automóvel seja
reduzida. A utilização de um método frear() deve afetar apenas um objeto em particular.
Todos os carros podem frear, mas a ação em um objeto afeta apenas o objeto em questão.
        Apesar da independência de cada objeto, para que um sistema funcione é
necessário que os objetos interajam. A interação entre objetos ocorre através da troca de
mensagens. Uma mensagem representa o ato de um objeto de uma classe chamar algum
método que outro objeto possua, fazendo com que este comportamento seja executado.
É comum esta ação ser chamada de ativação ou invocação de um método. Em analogia
com a programação estruturada, uma mensagem pode ser vista como uma chamada a
procedimento, inclusive com o retorno de um resultado a partir da execução deste método,
como ilustrado na Figura 20.




                                                                                                             25
Programação II




                                      Figura 20 – Ilustração do envio de uma mensagem para um objeto



                               Para um objeto invocar um método em outro objeto é necessário que obtenha uma
                      referencia ao objeto-alvo. Como cada objeto precisa ser identificado de forma unívoca (ou
                      seja, de forma exclusiva), faz-se então necessário definir um identificador para cada objeto.
                      Tome como exemplo a Figura 21. A classe Estudante define as características gerais de
                      um aluno. O método imprimirNome() é definido para apresentar tanto o nome do aluno,
                      quanto seu curso.




                                                    Figura 21 – Referências para objetos



                              Existem dois objetos que representam dois alunos distintos. Para isso, cada objeto
                      tem um identificador único. Para o aluno cujo nome é Fernando, o identificador do objeto é
                      aluno1, enquanto para o outro aluno, aluno2. Para se mandar uma mensagem para um dos
                      objetos utiliza-se a chamada “sintaxe do ponto” (dot syntax). Esta sintaxe indica que o acesso
                      a um atributo ou método de um objeto deve ser feita utilizando a forma “objeto.método”
                      ou “objeto.atributo”. No nosso exemplo, para chamar o método imprimirNome no objeto
                      aluno1, deve ser utilizada a notação aluno1.imprimirNome(). Dessa forma, representa-se a
                      ativação de uma mensagem neste objeto.


                      2.2. Agregação/Composição

                               A ideia de agregação ou composição estabelece a criação de novas classes de
                      objetos a partir da junção de classes já existentes. Essa ideia de composição é muito comum
                      para se representar relações do tipo todo-parte, como no caso de uma turma ser composta
                      por instâncias de outras classes, como um professor, um conjunto de alunos, dentre outros.
                             Da mesma forma que a classificação/instanciação são processos inversos, para a
                      composição de classes são definidas duas operações diferentes:

26
Programação II



    »   Operação de Agregação: Quando unimos um conjunto de objetos para formarmos
        um novo objeto;
    »   Operação de Decomposição: Quando, analisando um objeto, isolamos cada um de
        seus componentes.
        Veja o seguinte exemplo:




                            Figura 22 – Agregação/Decomposição



        Neste exemplo, a classe Automóvel pode ser decomposta nas classes Placa e Motor.
Este processo, chamado de decomposição, realiza uma análise sobre a classe Automóvel
e aplica um refinamento. Refinar significa deixar ainda mais claro a estrutura de um
determinado conceito. O processo inverso faz uma síntese de conceitos já existentes para
criar um novo conceito.
        Há uma notação especial em UML para representar agregação, como ilustrado e
exemplificado na Figura 23. Um losango vazado é anexado à extremidade de um caminho de
associação ao lado do agregado (o todo) para indicar agregação.




                 Figura 23 – Notação UML para agregação; Tipos de Agregação



       Há uma distinção entre dois tipos de agregação: a agregação compartilhada e a
composição. No primeiro tipo, representado pela ideia de uma disciplina que contem um


                                                                                                       27
Programação II



                      professor e uma sala vinculada, objetos contidos podem existir sem serem parte do objeto
                      que os contém. Em outras palavras, um professor continuará a existir, mesmo que não haja
                      o conceito Disciplina.
                               No caso da composição, objetos contidos não fazem sentido fora do contexto do
                      objeto que os contém. No exemplo apresentado, um pedido contem itens e um Cliente
                      vinculado. Se você destruir o pedido, os itens são destruídos junto, pois eles não tem sentido
                      fora do pedido. Neste caso, o losango anexado à extremidade da classe agregadora deve ser
                      preenchido, e não vazado.


                      2.3. Associações Simples

                               As entidades envolvidas apresentam existências independentes, mas existe uma
                      ligação entre elas. A agregação não é única forma de relacionamento entre objetos e classes.
                      Classes e objetos podem formar associações, que consistem na descrição genérica de uma
                      ou mais ligações entre as classes, permitindo que objetos de uma classe utilizem recursos
                      de outros objetos. Ao se estabelecer associações entre classes, em geral se estabelece o
                      significado de uma classe “usar” ou “possuir” outra. Para representar associações entre
                      classes, UML utiliza uma linha unindo as duas classes. Alguns exemplos de associações são
                      descritas abaixo.




                                                   Figura 24 – Associações entre classes



                               Nos exemplos acima, temos que um cliente está vinculado a um produto, e
                      vice-versa. Uma conta possui um histórico de transações. Um hóspede está vinculado
                      à um quarto. Associações podem ainda ser refinadas inserindo a multiplicidade nos
                      relacionamentos entre classes. Por exemplo, um único cliente pode estar vinculado a zero
                      ou mais (sem limites) pedidos. Um velocista pode participar de zero ou mais corridas, e uma
                      corrida deve ter no mínimo dois e no máximo seis velocistas.


                      2.4. Encapsulamento

                               Um dos aspectos mais positivos da programação modular foi a ideia de
                      encapsulamento de informações. A programação orientada a objetos preserva este
                      conceito. Encapsular dados em OO consiste em separar os aspectos externos de um objeto,
                      os quais são acessíveis a outros objetos, dos detalhes internos de implementação do objeto,
                      os quais permanecem escondidos dos outros objetos. O uso de encapsulamento evita que
                      objetos possuam grandes dependências entre si, de modo que uma simples mudança em
                      um objeto possa trazer grandes efeitos colaterais e problemas para outros objetos.
                              Como vimos no capítulo I, o conceito de encapsulamento não é exclusivo da
                      abordagem de orientação a objetos. Entretanto, a habilidade de se combinar estrutura de
                      dados e comportamento em uma única entidade torna o encapsulamento mais elegante
                      e mais poderoso do que em linguagens convencionais que separam estruturas de dados e
                      comportamento.

28
Programação II



        No paradigma OO, o encapsulamento institui conceitos e regras que ajudam a
promover a modularidade entre objetos. Para isso, o acesso a componentes de um objeto
é controlado e, especialmente, os atributos de um objeto só devem ser modificados pelos
métodos do próprio objeto. Veja como isso ajuda a proteger um programa. Imagine a classe
Conta que representa uma conta corrente, cujos atributos são seu número e seu saldo na
Figura 25.




                          Figura 25 – O benefício do encapsulamento



        De acordo com projeto, o saldo de uma conta não pode ser menor que zero. Mas
da forma como até agora conhecemos classes, o acesso a atributos e métodos é liberado.
Logo, qualquer objeto poderia ter o atributo saldo acessado diretamente, e modificado para
um valor inválido, como representado no exemplo. Para sanar este problema, linguagens
orientadas a objetos oferecem mecanismo que modificam a visibilidade (escopo) de
atributos e métodos. É possível então estabelecer que todos os atributos de uma classe só
possam ser acessados de métodos definidos dentro da própria classe. É dito então que o
escopo deste método é privado à sua classe.
        No nosso exemplo, a modificação do saldo de uma conta só poderá ser feita através
do método debitar(valor) que internamente estabelece regras que não permitem que o
saldo da conta fique negativo.
         A ideia do encapsulamento faz também com que o sistema não dependa das
implementações internas das classes, mas sim de suas interfaces. A interface de um objeto é
representada pelo conjunto de todos os métodos que este objeto oferece a outros objetos.
A interface de um objeto é que é externamente visível, e que protege dados internos, além
de outras operações que não devem ser disponibilizadas ao mundo externo.
         Imagine uma classe que represente o conceito de uma coleção de pessoas, e que
forneça métodos para manipular esta coleção, como inserir uma pessoa, consultar uma
pessoa pelo nome, etc. Internamente, esta classe poderia utilizar diferentes estruturas para
guardar a coleção de pessoas, como um vetor, uma lista dinâmica ou mesmo um banco de
dados. Porém, para quem vai utilizar algum objeto desta classe, isso não importa. O que
importa é que exista um método para inserir, outro para consultar, e assim por diante. Desta
forma, alterações dentro da classe não afetarão o restante do sistema. Por exemplo, pode-
se trocar a implementação interna da classe, mudando de um vetor para o banco de dados.
Se a interface for mantida, os objetos que usam não sofreram nenhum impacto, o que torna
a manutenção mais fácil.
        Por estes motivos, na orientação a objetos é muita utilizada a expressão “programar


                                                                                                           29
Programação II



                      para a interface”. Esta expressão indica a ideia que a interface de um objeto representa
                      um contrato entre uma classe de objetos. Enquanto o contrato for mantido, objetos que
                      dependam dos métodos de uma classe não serão prejudicados.


                      2.5. Generalização/Especialização (Herança)

                               Generalização e especialização são abstrações que permitem o reuso de objetos
                      através da criação de classes de objetos a partir de outras classes. No caso, a especialização
                      é o mecanismo pelo qual pode-se definir uma nova classe de objetos a partir de uma classe
                      já existente. Esta nova classe poderá aproveitar o comportamento e possíveis atributos
                      da classe estendida. A classe sendo refinada é chamada de superclasse ou classe base,
                      enquanto que a versão refinada da classe é chamada uma subclasse ou classe derivada. A
                      generalização é o inverso da especialização. A Figura 26 ilustra esta relação:




                                 Figura 26 – Generalização/Especialização, a base para a Herança entre classes



                              Neste exemplo, a superclasse Estudante é refinada em dois tipos mais específicos, os
                      de graduação e os de pós-graduação. Diz-se que cada classe derivada herda as características
                      de sua classe base. Por conta disso é mais comum essa abstração serem tratadas em
                      linguagens de programação orientadas a objetos como Herança. No nosso exemplo, a classe
                      Estudante poderia ter como atributos: nome ou instituição vinculada, estes também são
                      atributos de estudantes de graduação ou pós-graduação. Cada classe derivada não apenas
                      herda as características de seu ancestral como também pode acrescentar seus atributos e
                      operações específicos, como o curso para o Estudante de Graduação.
                               Em UML, a notação para generalização é representada por uma associação entre
                      superclasse e subclasses, onde um triângulo é posto na extremidade próxima à superclasse
                      (Figura 27).




30
Programação II




      Figura 27 – Representação UML para Herança; Exemplo para uma hierarquia de classes



        É importante salientar que a herança não vale apenas para dados, mas também
para métodos. No mesmo exemplo, a classe Estudante define um método imprimeDados.
Portanto, as subclasses da classe Estudante também herdam este comportamento. Com
isto, embora o método não seja definido na classe EstudanteGraduação ou EstudantePos,
qualquer objeto de uma destas duas classes pode ter o método imprimeDados sendo
invocado.
        A correta chamada de métodos ou o acesso a atributos em classes que
possuam uma relação de herança ocorre através da busca nas classes que participam da
hierarquia. Exemplificando: quando um método é chamado em um objeto de uma classe,
a especificação deste método é procurada na classe deste objeto. Se este método não é
encontrado, busca-se então na definição de sua superclasse, e assim por diante, pois uma
hierarquia de herança pode ser formada por várias classes, recursivamente aplicada a um
número arbitrário de níveis. A Figura 28 exemplifica uma relação de herança em mais de um
nível.




                            Figura 28 – Múltiplos níveis de herança




                                                                                                            31
Programação II



                              Neste exemplo, o Estudante de Graduação além do curso, possui também como
                      atributos herdados a matricula (da classe Estudante) e o nome (da classe Pessoa).
                               Uma subclasse pode também sobrepor uma característica de sua superclasse,
                      o que significa que a nova característica local à subclasse irá substituir a característica de
                      sua superclasse. Neste caso, esta ação é chamada de sobreposição. Ainda no exemplo
                      anterior, a classe Estudante sobrepõe o método imprimeDados da classe Pessoa. Em outras
                      palavras, a execução deste método em objetos da classe Estudante obedecerá a esta nova
                      definição. Note que esta alteração também afeta objetos das classes EstudanteGraduação
                      e EstudantePos. Objetos dos tipos Pessoa e Empregado executam a definição original do
                      método.
                               A definição e uso de herança traz consigo também um princípio muito importante
                      para a orientação a objetos que é o princípio da substituição. Este princípio se baseia no
                      fato que, se uma subclasse herda métodos e atributos de sua superclasse, em qualquer
                      lugar de um programa que você possa utilizar uma instância de superclasse, você também
                      deve poder utilizar uma instância de qualquer subclasse desta classe. Embora pareça
                      complicado, imagine um programa que faz uma chamada ao método imprimeDados de
                      um objeto Pessoa, de acordo com a hierarquia de classes da Figura 27. Pelo princípio da
                      substituição, você pode substituir este objeto Pessoa por qualquer outro objeto que seja
                      instância de alguma subclasse de Pessoa, como Estudante, Empregado, EstudantePos ou
                      EstudanteGradução. Como todos eles vão possuir o método imprimeDados, o programa vai
                      continuar a funcionar sem problemas. Este princípio é muito útil para facilitar a extensão de
                      programas.

                              Herança Simples e Herança Múltipla

                              A herança pode ser de dois tipos: Simples e Múltipla. A herança simples é quando
                      uma classe é subclasse de somente uma superclasse, enquanto a herança múltipla ocorre
                      quando uma classe é subclasse de várias superclasses e, consequentemente, herda as
                      características de cada uma delas. Os exemplos que vimos até agora foram todos de herança
                      simples. A Figura 29 apresenta um exemplo de uma herança múltipla.




                                                  Figura 29 – Exemplo de Herança Múltipla



                              Neste caso, note que a classe VeiculoAnfibio possui duas superclasses, Carro e
                      Barco. Desta forma, ela herda métodos e atributos destas duas classes. Herança múltipla
                      não se limita a apenas duas classes, de acordo com o contexto do mundo que se queira
                      modelar. Porém, a herança múltipla traz um problema: o conflito de atributos ou métodos
                      herdados das superclasses. Em nosso exemplo, note que tanto Carro quanto Barco possuem
                      um método parar. Imagine então o que aconteceria se fosse feita uma chamada ao método
                      parar em um objeto do tipo VeiculoAnfibio. Qual implementação de parar deveria ser
                      chamada?



32
Programação II



         Por conta dessa e de outras questões, a Herança Múltipla não é implementada em
todas linguagens de programação, como no caso de Java. Porém, pode ser encontrada em
outras linguagens como C++ e SmallTalk.


2.6. Polimorfismo

        O termo polimorfismo é originário do grego, e etimologicamente quer dizer “muitas
formas”. Na orientação a objetos, isso significa que um mesmo tipo de objeto, sob certas
condições, pode realizar ações diferentes ao receber uma mesma mensagem. Ou seja,
objetos podem ter reações diferentes ao mesmo estímulo (Figura 30).




         Figura 30 – Polimorfismo: Objetos têm diferentes reações a um mesmo estímulo



        Polimorfismo permite o envio de uma mesma mensagem a objetos distintos, onde
cada objeto responde da maneira mais apropriada para a classe chamadora. No exemplo
da Figura 30, a mesma mensagem “desenhar” pode ser enviada a três objetos distintos: o
quadrado, o círculo e o triângulo. Os três sabem como tratar esta mensagem, porém cada
um realizará ações diferentes.
        Existem dois tipos principais de polimorfismo: a sobrecarga e a sobreposição.
        Na sobrecarga, uma mesma classe de objetos possui métodos com o mesmo nome,
porém quantidade ou tipo de parâmetros diferentes. No momento da chamada do método,
dependendo do parâmetro, um método ou outro será chamado. Por exemplo, a classe
Pessoa (Figura 31) possui dois métodos imprimir. O primeiro recebe apenas um parâmetro,
enquanto o segundo recebe dois.




                              Figura 31 – Sobrecarga de métodos



         Já a sobreposição ocorre somente associada à herança. Quando um método
definido na superclasse não serve da forma original para a subclasse, ele tem de ser
redefinido. Como na redefinição a assinatura deve ser mantida, o novo método sobrepõe o
método definido na superclasse.
       Veja como exemplo a Figura 32. Existem dois tipos de Funcionário: o que recebe
um salário fixo (Empregado) e outro cujo salário é calculado de acordo com suas vendas


                                                                                                         33
Programação II



                      (EmpregadoComissão). O segundo tipo tem as mesmas características do primeiro, portanto
                      convém que se utilize herança para reaproveitar seus dados. Porém, o calculo de seu salário
                      é totalmente diferente. Neste caso, a subclasse modifica (sobrepõe) o comportamento do
                      método que calcula o salário para a classe EmpregadoComissão.




                                                  Figura 32 – Sobreposição de métodos



                               Neste caso, quando um objeto for do tipo Empregado, o calculo do salário obedecerá
                      a regra definida na superclasse. Mas quando o objeto for do tipo EmpregadoComissão, a
                      regra utilizada é aquela que foi redefinida nesta classe. Em resumo:

                          »   O método a ser chamado é aquele pertencente ao objeto o qual a chamada está
                              relacionada;
                          »   Caso o objeto não possua este método, a chamada é transferida para a superclasse,
                              e assim por diante até que o método seja encontrado;
                              Porém, ao contrário da sobreposição, métodos sobrepostos na subclasse precisam
                      ter a mesma assinatura de seus equivalentes na superclasse. Em outras palavras, precisam
                      ter o mesmo nome; o mesmo número de parâmetros e o mesmo tipo de parâmetros de
                      entrada e saída.


                                   Exercícios


                          1. No contexto da programação orientada a objetos, o que é um objeto?
                          2. No contexto da programação orientada a objetos, o que é uma classe? Diga também
                             o que são métodos e variáveis de instância.
                          3. Indique qual é o principal benefício obtido quando os atributos de uma classe não
                             são visíveis a outras classes? Qual é o nome desta técnica de programação?
                          4. Explique o que é o relacionamento de herança entre classes.
                          5. Para você, qual o benefício do polimorfismo no paradigma orientado a objetos?
                          6. Utilizando orientação a objetos, indique quais seriam as classes, seus atributos,
                             métodos e associações para os seguintes sistemas:
                               a) Uma universidade;
                               b) Um acervo de mídias (CDs e DVDs)
                               c) Um filme.




34
Programação II




             Vamos Revisar?


         Neste capítulo, você foi apresentado a uma nova forma de organizar os conceitos
para criação de programas de computador. A orientação a objetos baseia-se em uma
aproximação da forma como os seres humanos organizam e realizam ações no mundo real.
Para isso, novas abstrações como classificação, agregação, associação, dentre outras são
fundamentais para que os programas sejam organizados de forma a permitir um maior reuso
de código e maior flexibilidade de manutenção. Conceitos como classes, objetos, métodos
e atributos são fundamentais em linguagens orientadas a objetos, vão fazer parte do dia a
dia deste curso. A partir deles, conceitos mais avançados como herança e polimorfismo são
gerados, e serão mais detalhados adiante nesta disciplina. Por enquanto, é importante que
os conceitos deste capítulo seja amadurecidos em sua cabeça.




                                                                                                        35
Programação II




                               Capítulo 3


                          O que vamos estudar neste capítulo?

                          Neste capítulo, vamos estudar os seguintes temas:

                      »   Linguagem de Programação Java
                      »   Java Software Development Kit – JSDK
                      »   O ambiente de programação JCreator

                          Metas

                          Após o estudo deste capítulo, esperamos que você consiga:

                      »   Identificar as principais características da Linguagem Java;
                      »   Instalar e configurar o Kit de desenvolvimento necessário para compilar e executar
                          seus programas em Java;
                      »   Instalar o ambiente de programação JCreator;




36
Programação II




Capítulo 3 – A Linguagem Java

             Vamos conversar sobre o assunto?


         Nos capítulos iniciais deste volume você aprendeu sobre a necessidade de
melhorar a forma como organizamos os conceitos em linguagens de programação e como
a orientação a objetos busca melhorar o reuso e a manutenção de programas. Bem, até
agora, tudo foi bastante teórico. Então chegou a hora de começarmos a ver como na prática
isso tudo funciona. Para isto, este capítulo introduz a linguagem de programação orientada
a objetos mais popular no mundo: Java.




1. Introdução
                                                                                                   Você Sabia?
        A linguagem de programação Java tem origem no início da década de 90, dentro
da Sun Microsystems. Na época, uma equipe liderada por Patrick Naughton, Mike Sheridan,
e James Gosling tinha como objetivo projetar uma nova linguagem de programação capaz
de criar softwares capazes de comunicar diferentes dispositivos entre si. Originalmente,
batizou-se esta linguagem de Oak (carvalho, em inglês), em homenagem a um espécie de
árvore que os integrantes do projeto avistavam de sua sala.
        Inicialmente a proposta de interoperabilidade de programas não foi muito bem
aceita pelo mercado, o que então fez com os objetivos fossem modificados. Na época, o        Você sabia que a
                                                                                             linguagem Java tem
uso da Internet estava crescendo vertiginosamente. Foi então que a Sun viu nesta expansão    esse nome devido a
uma oportunidade de usar Oak. A linguagem passaria então a ser voltada para construir        um café?
aplicações para Web. A linguagem foi rebatizada e passou a se chamar Java, sendo             Durante o projeto os
apresentada oficialmente em 1995.                                                            participantes tomava
                                                                                             muito café, e gostavam
       Desde então, Java foi rapidamente adotada pelo mundo, mais rapidamente que            principalmente de
qualquer outra linguagem de programação até então. Grandes fornecedores de tecnologia        um proveniente da
como IBM, Oracle, Netscape, dentre outros, passaram a apoiar Java.                           ilha de Java. No meio
                                                                                             do projeto Green,
        A linguagem evoluiu muito ao longo dos anos. Hoje, mas que uma linguagem,            os projetistas foram
                                                                                             avisados que já havia
Java pode ser vista como uma plataforma de desenvolvimento e execução de programas
                                                                                             uma linguagem com
em diversas plataformas. Você encontra programas Java na Web, dos telefones celulares,       o nome de oak, que
mainframes, cartões inteligentes, dentre outros. Com isso, a linguagem é dividida em 3       inicialmente era o
grandes segmentos:                                                                           escolhido. Com isso, os
                                                                                             projetistas resolveram
    1. JEE (Java Enterprise Edition): indicado para aplicações coorporativas, com            homenagear a ilha que
                                                                                             produzia o café tão
       necessidade gerenciamento de transações, balanceamento de carga, concorrência,        apreciado por todos.
       dentre outros;
    2. JSE (Java Standar Editon): é o ambiente de desenvolvimento mais utilizado. Isso
       porque seu uso é voltado a PCs e servidores, onde há bem mais necessidade de
       aplicações;
    3. JME (Java Micro Edition): é o ambiente de desenvolvimento para dispositivos
       móveis ou portáteis, como telefones celulares e palmtops.
        Hoje, estima-se que haja uma comunidade de mais de quatro milhões de

                                                                                                               37
Programação II



                      programadores Java no mundo. Existem também grupos de usuários Java, chamados JUGs
                      (Java User Groups), que são utilizados para troca de ideias, dúvidas e melhores práticas no
                      uso da tecnologia Java. No Brasil, existem vários, como o DF-JUG (de Brasília) ou CE- JUG(do
                      Ceará). Existem diversos livros publicados sobre a linguagem, além de diversos ambientes
                      de programação e desenvolvimento.



                      2. Características da Linguagem
                             Durante seu projeto, a linguagem Java teve uma série de requisitos que podem se
                      apontados como fatores de seu sucesso.

                          1. Java é orientada a objetos: Java foi baseada no modelo de outras linguagens de
                             programação OO, no caso, Simula67 e SmallTalk. Com isso, os conceitos de herança,
                             polimorfismo e encapsulamento são implementados pela linguagem. A sintaxe e
                             seu sistema de tipos é bem parecido com C e C++, o que facilitou a migração de
                             programação de programadores já acostumados com estas linguagens;
                          2. Java é portável: Este conceito indica que um mesmo programa escrito em Java
                             pode ser executado em diferentes plataformas hardware ou sistema, sem grandes
                             ou nenhuma mudanças. Por conta desta característica, é comum se associar a Java
                             o seguinte jargão: “escreva uma vez, execute em qualquer lugar;
                          3. Java é segura, confiável e robusta: Ao contrário de suas predecessoras, Java não
                             trabalha com ponteiros. Em outras palavras, um programador Java não tem acesso
                             direto a posições de memória, um dos grandes problemas para quem trabalha
                             com linguagens como C ou C++. Java possui um mecanismo de tratamento de
                             exceções em que os erros que possam vir a ocorrer durante operações efetuadas
                             são tratadas paralelamente em outro trecho de código do sistema. Um erro que
                             durante a execução do programa poderá ser capturado sem imprevistos como, por
                             exemplo, acessos inválidos de memória do sistema operacional, ou do gerenciador
                             de arquivos, que podem acarretar problemas como o travamento, desligamento do
                             computador e perda de arquivos significativos;
                          4. Java promove reuso e facilita a manutenabilidade: Java possibilita a criação de
                             componentes reutilizáveis, ou seja, uma vez criadas funcionalidades para os
                             mesmos, estes poderão ser reutilizáveis posteriormente. Com isso é proporcionado
                             um baixo custo de produção e manutenção de códigos gerados com os demais
                             sistemas que venham a ser desenvolvidos;
                          5. Java é distribuída: Java possui a capacidade de compartilhamento de informações
                             possibilitando a distribuição de tal forma que haja processamento em máquinas
                             distintas. Possui integração com o protocolo TCP/IP que facilita a programação para
                             acessos remotos, utilizando protocolos como: HTTP e FTP;
                          6. Java permite a carga dinâmica de aplicações: Java oferece o recurso de que
                             aplicações chamadas applets possam ser carregadas remotamente e executadas no
                             contexto de um browser, ao ler uma página na Web. Ao fazer isso, Java introduziu
                             a interatividade na Web, permitindo que aplicações pudessem ser descarregadas
                             e utilizadas automaticamente por usuários, sem necessidade de instalação, ou
                             atualizações de versões. Ao mesmo tempo, applets possuem um criterioso modelo
                             de segurança que previne o acesso de aplicações remotas a possíveis ações danosas
                             no computador do usuário que rode um applet;
                          7. Java é livre e gratuita: Você não paga nada para criar um programa em Java. O
                             software para execução e construção de programas é disponibilizado gratuitamente

38
Programação II



        na Internet. Além disso, existem vários ambientes gratuitos para facilitar a
        construção e depuração de programas Java.



3. Máquina Virtual Java: o alcance de
portabilidade
          Uma das características mais importantes da linguagem Java é a portabilidade. Para
isto, Java promove o conceito que nada na linguagem deve ser específico de uma plataforma
específica. O que na realidade Java faz, é criar a ideia de um computador abstrato sobre o
qual o programa deve ser executado. Esse computador abstrato é chamado de máquina
virtual Java (JVM).
        Na realidade, a máquina virtual Java é uma especificação fornecida a início pela
Sun, e seu funcionamento une a ideia de compilação e interpretação de programas. Vamos
ver como isso funciona.
        Para criar um programa Java precisamos criar sua especificação através da sintaxe
da linguagem. Como em praticamente toda linguagem de programação isso é feito através
da edição de um arquivo texto.
         A partir de um programa escrito corretamente, a etapa que segue é a compilação do
programa para geração de sua versão executável. Aqui vem uma grande diferença. Em vez
de gerar um arquivo executável que é voltado para um computador ou sistema operacional
específico, Java gera uma versão intermediária do programa, o bytecode.
        O bytecode é um arquivo neutro e independente de plataforma. Ele representa
o programa executável e livre de erros, como uma linguagem de máquina destinada a
um processador virtual especificado pela máquina virtual Java. Desta forma, qualquer
implementação de uma máquina virtual Java deve ser capaz de executar este programa. O
que de fato acontece, pois hoje existem implementações da máquina virtual Java para as
mais diversas plataformas, como Windows, Linux, MacOS, dentre outros (Figura 33).




             Figura 33 – O processo de compilação e execução de um programa Java



        A JVM utiliza o mecanismo de interpretação para executar os bytecodes que
correspondem ao programa originalmente escrito pelo programador. O uso de uma
máquina virtual acarreta em um tempo a mais na execução do programa, o que indica que
programas escritos em Java tendem a ser mais lentos que programas equivalentes escritos
em C ou C++. Porém, a facilidade na migração de um sistema entre diferentes plataformas é
um requisito cada vez mais importante na construção das aplicações modernas. Ou seja, é
um benefício que se paga.
       Além disso, as atuais implementações de JVM fazem uma série de otimizações que
diminuem a diferença em relação à execução de um programa Java e programas compilados
diretamente para uma plataforma específica.



                                                                                                           39
Programação II



                      4. Codificando um primeiro programa Java
                               Uma forma muito utilizada para promover a familiarização com uma nova linguagem
                      é a criação de um programa simples que apresenta uma mensagem na tela. Vamos aqui
                      também utilizar esta estratégia. Para isso, vamos utilizar um editor de textos plano (o bloco
                      de notas, por exemplo) para editar nosso programa.
                              Um programa em Java é um arquivo texto, que por padrão, possui a extensão .java.
                      A Figura 34 apresenta o programa AloMundo.java, que será utilizado para nosso primeiro
                      contato com a linguagem.




                                                        Figura 34 – Programa AloMundo.java



                             Digite este programa e grave o arquivo em um diretório de seu computador. No
                      meu caso, eu criei um diretório c:Java e utilizarei o mesmo em meus exemplos. Vamos
                      então analisar este programa. Importante: Java faz diferenciação entre letras minúsculas
                      e maiúsculas. Portanto, ao digitar o programa AloMundo, faça-o mantendo o mesmo
                      padrão em relação ao texto apresentado neste capítulo, inclusive para o nome do arquivo
                      AloMundo.java.
                               A primeira linha marca o início da declaração de uma classe em Java. Em Java, tudo é
                      uma classe. Como visto no capítulo anterior, classes são utilizadas para criar objetos. Então,
                      a definição de uma classe em Java utiliza a palavra reservada class. Associada à definição
                      da classe, temos outra palavra reservada: public. Esta palavra reservada é um qualificador,
                      que no caso indica a visibilidade da classe, e que será detalhada mais adiante no curso.
                      Por enquanto, guarde apenas na cabeça que a definição de uma classe segue este padrão:
                      public class <NOME_DA_CLASSE>.
                               Seguido a definição da classe, vem a definição do corpo da classe. Java segue um
                      padrão em que existem blocos que agrupam trechos de código e limitam o escopo de
                      variáveis. Todo bloco em Java é limitado por chaves (“{“ e”}”). No nosso exemplo, as chaves
                      que limitam o bloco da classe estão nas linhas 1 e 7.

                               O corpo da classe AloMundo é extremamente simples. Existe apenas um método:

                       public static void main(String args[]){
                           System.out.println(“Alô mundo!!!”);
                       }

                              Este método representa o ponto de entrada da classe. De forma análoga com C,
                      este método é aquele que é executado quando pedimos para o interpretador Java executar


40
Programação II



a classe. A partir deste ponto, outros métodos podem ser chamados, objetos podem ser
criados, etc. Vamos analisar um pouco mais a fundo a assinatura deste método.


                 Assim como para a classe, deve-se declarar a visibilidade do método. Neste caso, a
    public
                 ideia que qualquer classe pode executar este método.

                 É um outro qualificador, que indica que o método deve ser compartilhado por
                 todos os objetos que são criados a partir desta classe. Os métodos static podem ser
                 invocados, mesmo quando não foi criado nenhum objeto para a classe. Detalhes
    static       sobre métodos estáticos serão vistos posteriormente no curso. Por hora, você
                 precisa saber que particularmente o método main precisa ter essa qualificação
                 porque ele é chamado sem que se crie nenhum objeto de sua classe (a classe
                 AloMundo).

                 É o valor de retorno da função, quando a função não retorna nenhum valor ela
    void         retorna void. Vamos ver no curso que métodos, assim como funções podem
                 retornar valores como números, palavras, vetores e, é claro, objetos.

                 Toda classe em Java deve conter métodos. Porém, existe um método que torna
                 uma classe um programa executável. Este método é chamado de método principal
    main
                 (main). Este é um nome particular de método que indica para o compilador o início
                 do programa.

                 É o argumento de main e por consequência do programa todo, ele é um vetor
   (String
                 (array) de Strings que é formado quando são passados ou não argumentos através
   args[])
                 da invocação do nome do programa na linha de comando do sistema operacional.

        Então, resumindo: Toda classe que quiser executar ações deve fornecer um método
com a assinatura:

public static void main(String args[])

       A partir daí, como em todo programa, seguem-se as instruções. No nosso caso,
temos uma única instrução:

System.out.println(“Alo Mundo!”);

         Esta instrução representa a maneia mais simples de imprimir mensagens na tela
de seu computador. Como dito anteriormente, tudo em Java é representado através de
classes e objetos. Esta instrução acima também segue este padrão. System é o nome de
uma classe fornecida pela linguagem Java e que representa o sistema onde o programa está
sendo executado. Esta classe possui uma série de atributos e métodos. Um destes atributos
é out. Este atributo representa a saída padrão do sistema, no caso, a tela. Na realidade,
out é um objeto de outra classe (PrintStream), que permite escrever mensagens através de
seus métodos. Dentre os vários métodos fornecidos, existe o println, que imprime a String
passada como parâmentro e e posiciona o cursor na linha abaixo. Analogamente, existe
também o método print que não avança linha. Por hora você pode guardar esta linha de
código como o comando para imprimir mensagens na tela, onde o argumento que vem
entre aspas é a String a ser impressa. O ; “ponto e vírgula” separa os comandos, sendo
portanto obrigatório para encerrar cada instrução.
        Visto isso, vamos ver como este programa deve ser executado.




                                                                                                                        41
Programação II



                      5. JSDK – Java Software Development Kit
                              Bem, visto a definição de um programa simples em Java, vamos aos próximos
                      passos, que seriam sua compilação e posterior execução. Para, precisamos então ter acesso
                      às ferramentas que permitam a realização destes passos.
                                 Formalmente, a linguagem tem padronizada a sua especificação, mas não a
                      implementação das ferramentas necessárias à execução de seus programas. No entanto,
                      a Sun fornece uma implementação de referência, assim como uma série de programas
                      utilitários para a plataforma Java. Este conjunto é chamado de JDSK (Java Software
                      Development Kit) é está disponível gratuitamente no site da Sun (http://java.sun.com).
                               O JSDK ou simplesmente JDK possui versões para diferentes plataformas, como
                      Windows ou Linux. Logo, a primeira coisa que você precisar fazer é baixar a versão correta
                      para a sua plataforma (no caso, sistema operacional). Neste texto, eu utilizo a versão do JDK
                      para Windows 7.
                               Após instalar, é criada uma estrutura de diretórios semelhante à descrita na Figura
                      35, onde o nome do diretório jdk1.X varia de acordo com a versão a ser instalada. Nesta
                      estrutura destaca-se o diretório bin, que guarda a principais ferramentas necessárias para
                      execução e compilação dos programas. Portanto, é extremante recomendável que você
                      inclua este diretório no caminho de busca da execução de programas em seu sistema
                      operacional. Para isto, basta atualizar a variável PATH, fazendo ela também apontar para
                      este diretório.




                                                 Figura 35 – Estrutura de diretórios do JSDK



                               Todas as ferramentas fornecidas no JSDK através de linhas de comando. Ou seja,
                      para executá-las, basta abrir um prompt de comando e chamar a ferramenta. Dentre as
                      ferramentas fornecidas, existem aquelas que são indispensáveis à execução dos programas,
                      e outras que tem um grau de importância menor. Dentre estas destacam-se o compilador
                      javac e o interpretador java.
                             O compilador javac é o responsável pela geração dos bytecodes a partir de um
                      programa fonte em java. Para ser utilizado, a forma mais simples é utilizando a sintaxe:

                       javac <opções> NOME_CLASSE

                              Para o nosso exemplo, dentro do diretório onde se encontra a classe, basta digitar
                      este comando, que será gerada uma versão bytecode do programa AloMundo.java. Os
                      arquivos bytecode tem o mesmo nome da classe, porém com a extensão .class. A Figura 36
                      mostra o processo de compilação e o arquivo gerado para o programa AloMundo.

42
Programação II




                          Figura 36 – Compilação de um programa Java



         É importante dizer que se uma classe faz referência a outra classe, as duas são
compiladas. Se no mesmo diretório houver mais classes e quisermos compilar todas, é
possível utilizarmos mascaras. Por exemplo, para compilar todas a classes, utilizaríamos a
sintaxe:

 javac *.java

        É possível também por uma questão de organização, separar os arquivos bytecode
dos arquivos fonte. Para isto, pode-se utilizar a opção –d pode ser utilizado para especificar
uma localização diferente para armazenar o arquivo .class gerado após a compilação:

 javac AloMundo.java –d c:Javabytecode

          Uma vez gerado o bytecode, segue-se a execução do programa. Para isto deve-se
utilizar o interpretador java. Quando o bytecode é utilizado pelo interpretador, a extensão
.class é desconsiderada. Por este motivo, não é necessário especificá-la na linha de
comando. Sendo assim, , para executar o programa, utiliza-se a sintaxe:

 javac <opções> NOME_CLASSE

         A execução do nosso programa é apresentado na Figura 37.




                           Figura 37 – Execução de um programa Java



       Além destas ferramentas, o JSDK ainda fornece outros programas utilitários, que
embora não sejam essenciais como o compilador e o interpretador, oferecem recursos
importantes para o bom uso de Java.
         Por exemplo, a ferramenta javadoc representa um avanço no que diz respeito a
documentação de seus programas. Através de comentários em um formato padronizado
escrito no próprio código, a ferramenta javadoc gera automaticamente um conjunto de
páginas HTML, onde as informações sobre classes, métodos e atributos são organizadas
através de ligações dinâmicas, no formato já familiar aos sites da Internet. Vamos ver este

                                                                                                             43
Programação II



                      formato de documentação nos próximos capítulos de nosso curso.
                               A ferramenta jar é utilizada para empacotar arquivos Java. Em geral, arquivos .jar
                      empacotam arquivos .class somente. O empacotamento de arquivos .class pode ser útil
                      quando se deseja disponibilizar um programa para execução, mas o código não precisa ser
                      fornecido uma vez que nenhuma alteração será realizada no mesmo. De outra forma, um
                      .jar pode conter também arquivos .java. Alguns comandos possíveis com o comando jar são:

                                Para criar um arquivo .jar                       jar cf arquivo.jar *.class

                                Para listar o conteúdo de um arquivo .jar        jar tf arquivo.jar

                                Para extrair o conteúdo de um arquivo .jar       jar xf arquivo.jar

                              Outra utilização de empacotamento jar é quando se deseja disponibilizar um
                      conjunto de classes para reutilização por outras aplicações. Estes outras aplicações não
                      irão manipular diretamente esses classes empacotadas e nem vão “executar” essas classes,
                      mas sim, utilizá-las para o desenvolvimento de alguma aplicação. Neste caso, essas classes
                      empacotadas servem como bibliotecas que podem ser utilizadas por outras aplicações.
                             Como dito no início deste capítulo, um applet é um tipo de programa Java utilizado
                      em browsers web. Esses programas ficam armazenados em servidores web e quando da
                      execução, são carregados pela rede para serem executados nos browsers web.
                                Java fornece uma ferramenta para testar esse tipo de programa, sem a necessidade
                      de utilização de um servidor ou browser web. Para tal, basta utilizar o comando appletviewer.

                       appletviewer pagina.html

                              Onde, appletviewer é a ferramenta de visualização de Applets e pagina.html,
                      corresponde ao arquivo HTML no qual o applet será carregado para execução.



                      6. JCreator: Ambiente de programação de
                      iniciantes
                              Como você percebeu, para compilar e executar programas basta um editor de
                      textos e kit de desenvolvimento fornecido gratuitamente pela Sun. Porém, na prática, o
                      desenvolvimento de programas se dá por meio de ferramentas que facilitem ainda mais
                      este processo, os chamados ambientes integrados de desenvolvimento – IDE (do inglês,
                      Integrated Development Environment). Estes ambientes criam uma interface para o
                      programador, permitindo, entre outras coisas: a compilação e execução de programas
                      através de interfaces gráficas, ferramentas de depuração, dentre outras.
                              Existem vários ambientes de programação disponíveis para Java. Alguns são
                      gratuitos, outros não. Aqui segue uma pequena lista destas ferramentas:

                          »   Eclipse: IDE gratuita fornecida pelo projeto Eclipse, de código aberto, que fornece
                              uma série de extensões para facilitar a construção de programas de computador.
                              URL: http://www.eclipse.org/
                          »   Netbeans: IDE gratuita fornecida pela Sun microsystems. O NetBeans IDE é
                              um ambiente de desenvolvimento integrado gratuito e de código aberto para
                              desenvolvedores de software. URL: http://netbeans.org/
                          »   Jbuilder: IDE paga para desenvolvimento de aplicações na tecnologia Java criada
                              pela Borland. URL: http://www.borland.com/br/products/jbuilder/


44
Programação II



    »   BlueJ: IDE gratuita para desenvolvimento Java, desenvolvida principalmente para
        iniciação na programação orientada a objeto. URL: http://www.bluej.org/
        Destas ferramentas, destacam-se as 3 primeiras, principalmente para o
desenvolvimento profissional. Porém, devido a gama de funcionalidades que estas
apresentam, para um programador iniciante, elas podem mais confundir que ajudar.
Portanto, vamos utilizar nesta disciplina um ambiente de programação mais simples
chamado JCreator.
        JCreator é um IDE bem leve, que possui uma versão específica e gratuita para o
aprendizado de Java. Esta versão gratuita, LE(Learn Edition), for criado pela Xinox Software
e possibilita também o desenvolvimento em outras linguagens, como JavaScript,XML,HTML.
         O site de download da ferramenta é o http://www.jcreator.com. O tamanho de seu
instalador gira em torno de 4Mb, e o processo de instalação é bem simples. Seu único
requisito é que antes de sua instalação, o JSDK já deve estar instalado. A Figura 38 abaixo
mostra um screenshot da tela inicial do JCreator.




                              Figura 38 – Tela Inicial do JCreator



       O JCreator trabalha com a ideia de espaços de trabalho (workspaces) e projetos.
Um projeto possui um conjunto de classes que juntas constituem uma aplicação. Em geral,
uma aplicação Java é composta por centenas de arquivos. Um workspace é uma pasta no
seu computador onde ficam armazenadas as informações sobre um projeto.
         Para criar um projeto, utiliza-se o menu File > New > Project. O JCreator abrirá um
assistente (Figura 39) para que você possa escolher o tipo de projeto que você quer. Escolha
a opção Basic Java Application (Aplicação Básica Java) e pressione Next.




                                                                                                           45
Programação II




                                          Figura 39 – Jcreator Wizard: Criando um novo projeto



                             Escolha um nome para seu projeto e pressione Finish (Figura 40).




                                            Figura 40 – Jcreator Wizard: Nomeando o projeto



                              Confirme novamente a criação de projeto. Você deverá ter em sua tela agora
                      parecido com o apresentado na Figura 41.




                                                  Figura 41 – JCreator: Projeto Criado


46
Programação II



         Como você pode notar, o projeto é criado e uma classe com o mesmo nome do
projeto lhe é fornecida. Ela já vem com o esquema de uma classe que faz o mesmo que o
nosso exemplo AloMundo.java, contendo trechos de comentários que ainda serão vistos
no curso. Você pode obtar por trabalhar em cima desta classe ou criar uma nova classe.
Para isso, utilize novamente o menu File, na sequência File > New > Class. Aparece um novo
wizard para você. Digite o nome da classe AloMundo e pressione Finish. É apresentada para
você uma classe, de forma semelhante com a Figura 42.




                         Figura 42 – Classe AloMundo criada no JCreator



       Modifique a classe AloMundo fornecida pelo JCreator, deixando-o igual ao nosso
exemplo do início deste capitulo. Vamos agora compilar e executar nossa classe.
        A compilação de uma classe é obtida através da opção do menu Build. Você pode
optar por compilar uma única classe (Build) ou ou todas as classes do projeto (Build Project).
Há também botões de atalho para as duas opções           . Após compilar a classe, você deve
obter uma resposta na janela abaixo, chamada Build Output. No nosso caso, você deve
obter uma mensagem semelhante à descrita na Figura 43.




                 Figura 43 – Resultado de um compilação sem erros no JCreator



          Por fim, a execução da classe. Para isso, você utiliza o menu Run. Nele você pode
optar por executar o projeto ou a classe ativa. Todo projeto tem uma classe principal, que
seria a responsável por iniciar da aplicação. Isso pode ser configurado nas propriedades do
projeto. Vamos executar a classe AloMundo através da opção Run File. Para isso, certifique-
se que a classe AloMundo é que está sendo apresentada no JCreator. A execução vai disparar
uma nova compilação, e depois, na janela General Output, será apresentado o resultado da
execução do programa. Você também pode utilizar o botão de atalho para Executar a classe
(     ) . Você então deverá ver algo como na Figura 44.




                                                                                                             47
Programação II




                                     Figura 44 – Resultado da Execução da classe AloMundo no JCreator



                              Como você percebe, um ambiente como o JCreator é uma mão na roda para
                      evitarmos ter que trabalhar com as linhas de comando oferecidas pelo JSDK. O JCreator
                      ainda lhe fornece uma janela File View, onde são apresentados os arquivos de seu projeto
                      e uma janela Properties View, que mostra propriedades de diferentes itens de seu projeto,
                      como do próprio projeto.


                                   Exercícios


                          1. Baixe e instale o Kit de Desenvolvimento Java adequado para seu computador;
                          2. Crie o programa AloMundo descrito neste capítulo. Compile-o e execute-o
                             utilizando os programas apresentados no capítulo;
                          3. Edite o programa AloMundo e modifique o nome da classe para Alomundo. Para
                             isso, mude a linha “public class AloMundo{“ para “public class Alomundo{“. Compile
                             novamente. Qual o resultado da compilação?
                          4. Baixe e instale o JCreator;
                          5. Crie um projeto novo, com uma classe. Faça com esta classe imprima na tela seu
                             nome;
                          6. Compile e execute esta classe no JCreator.




                                     Minibiografia




                        James Gosling (Calgary, 19 de Maio de 1955) é conhecido como o pai da linguagem de
                        programação Java. Ele fez o projeto original do Java e implementou o seu primeiro compilador
                        e sua máquina virtual. Por este feito ele foi eleito para a United States National Academy of
                        Engineering. Gosling está desde 1984 na Sun Microsystems. Gosling trabalha desde 2006 como
                        CTO da Sun do grupo de desenvolvimento do produto.




48
Programação II




             Vamos Revisar?


        Neste último capítulo, você foi apresentado(a) à linguagem de programação mais
popular do mundo atualmente. O propósito deste capítulo foi principalmente apresentar
as características que fizeram de Java, uma linguagem tão bem aceita por programadores
no mundo todo. Posso afirmar com certeza que um destes motivos foi sua aderência ao
paradigma orientado a objetos. Além disso, destaca-se sua proposta de portabilidade
através de seu conceito de máquina virtual. Você também viu como é a estrutura de um
programa simples em Java, que também serviu de exemplo para uso do compilador e
interpretador inclusos no Kit de Desenvolvimento da linguagem. Por fim, você também
conheceu o JCreator, uma ambiente de programação leve e simples, porém muito útil para
programadores iniciantes na linguagem, e que será utilizado durante o curso para realização
dos exercícios durante a disciplina.




                                                                                                          49
Programação II




                      Conheça o Autor

                              Fernando Trinta

                               Sou professor de ciência de computação, formado pela Universidade Federal
                      do Maranhão. Tenho Mestrado e Doutorado em Ciência da Computação pelo Centro de
                      Informática da Universidade Federal de Pernambuco, com ênfase na área de Sistemas
                      Distribuídos. Durante minha pós-graduação, estive envolvido com os temas de objetos
                      distribuídos e educação a distância no Mestrado, e jogos digitais, middleware e computação
                      ubíqua no Doutorado. Trabalhei no desenvolvimento de sistemas em várias empresas,
                      privadas e públicas. Atualmente faço parte do corpo discente do Mestrado em Informática
                      Aplicada da Universidade de Fortaleza (UNIFOR), no Ceará. Além da informática, gosto
                      muito de esportes em geral e cinema. Mas nos últimos anos, duas novas paixões tomaram
                      conta do meu mundo: Ian e Ananda.




50

Mais conteúdo relacionado

PDF
PDF
JV_scratch_Como_Usar_04_02_2012
PDF
Tcc magno ronan ritzmann
PDF
Greicy2012 - Projeto de Aprendizagem - Planejamento FUNCAO
PDF
Moodle moot anais 2010
PDF
Analise dos diferentes tipos de software
PDF
Sistemas Cooperativos Aula 11 - Técnicas (Percepção e contexto, folksonomia)
DOCX
Pré-Projecto AREA
JV_scratch_Como_Usar_04_02_2012
Tcc magno ronan ritzmann
Greicy2012 - Projeto de Aprendizagem - Planejamento FUNCAO
Moodle moot anais 2010
Analise dos diferentes tipos de software
Sistemas Cooperativos Aula 11 - Técnicas (Percepção e contexto, folksonomia)
Pré-Projecto AREA

Semelhante a Programacao ii volume1_v_final (20)

PPT
Educação digital und_01_apresent
PDF
Unidade 1
DOCX
Tecnologias no cotidiano
DOCX
Tecnologias no cotidiano
PPTX
Caderno atividades módulo Elaboração de Projetos
PDF
Unidade 1
PDF
6 ano computacao e eu estudante
PDF
6 ano computacao e eu estudante
PDF
Projeto: NAVEGANDO EM DIREÇÃO AO FUTURO
PPT
Apresentação unidade ii
PPT
Apresentacao curso introedudigital 40h - 2012
PPT
Unidade 1 - Curso Introdução à Educação Digital
PDF
ATPS - Programação Estruturada II
PDF
(LP2) Tópico 00 - Apresentação da Disciplina
PDF
Pensamento Computacional, Programação e Robótica no 1º CEB
PDF
Orientação a objetos java
PPTX
Programação Orientada a Objetos - POO (IFPI)
PDF
Intro micro software
PDF
ACM Lost171
PDF
Poo frank
Educação digital und_01_apresent
Unidade 1
Tecnologias no cotidiano
Tecnologias no cotidiano
Caderno atividades módulo Elaboração de Projetos
Unidade 1
6 ano computacao e eu estudante
6 ano computacao e eu estudante
Projeto: NAVEGANDO EM DIREÇÃO AO FUTURO
Apresentação unidade ii
Apresentacao curso introedudigital 40h - 2012
Unidade 1 - Curso Introdução à Educação Digital
ATPS - Programação Estruturada II
(LP2) Tópico 00 - Apresentação da Disciplina
Pensamento Computacional, Programação e Robótica no 1º CEB
Orientação a objetos java
Programação Orientada a Objetos - POO (IFPI)
Intro micro software
ACM Lost171
Poo frank
Anúncio

Mais de CLEAN LOURENÇO (20)

PPTX
Produtos multiídia rosinalva lopes
PDF
Produção midias poloananas_cleanlourenco
PDF
V1nmerosnaturais 1.swf
PPSX
IV DIA D DA MATEMÁTICA 2011
PPTX
Evidências do projeto geometria e artes
PDF
Avaliação 6° ano - 2° b - 2011
PDF
Matematica discreta fasciculo_3_v06
PDF
Matematica discreta fasciculo_1_v7
PDF
Texto Dengue - Tocantins
PDF
7º ano ângulos
PDF
Avaliação 8° ano 2° av
PDF
Atividade 1 números inteiros
PDF
Atividade de matemática tratamento da informação - dengue
PDF
Atividade números inteiros operações
PDF
Banco de dados_-_volume_4_v10
PDF
Exemplo projeto-bd-assunto-2a-aval-bsi-lc
PDF
Livro banco de_dados_volume_03
PDF
Livro banco de_dados_volume_02
PDF
Projeto reforço escolar
PDF
Projeto de arte e matemática
Produtos multiídia rosinalva lopes
Produção midias poloananas_cleanlourenco
V1nmerosnaturais 1.swf
IV DIA D DA MATEMÁTICA 2011
Evidências do projeto geometria e artes
Avaliação 6° ano - 2° b - 2011
Matematica discreta fasciculo_3_v06
Matematica discreta fasciculo_1_v7
Texto Dengue - Tocantins
7º ano ângulos
Avaliação 8° ano 2° av
Atividade 1 números inteiros
Atividade de matemática tratamento da informação - dengue
Atividade números inteiros operações
Banco de dados_-_volume_4_v10
Exemplo projeto-bd-assunto-2a-aval-bsi-lc
Livro banco de_dados_volume_03
Livro banco de_dados_volume_02
Projeto reforço escolar
Projeto de arte e matemática
Anúncio

Programacao ii volume1_v_final

  • 1. UNIVERSIDADE FEDERAL RURAL DE PERNAMBUCO (UFRPE) COORDENAÇÃO GERAL DE EDUCAÇÃO A DISTÂNCIA (EAD/UFRPE) Programação II Fernando Antonio Mota Trinta Volume 1 Recife, 2010
  • 2. Universidade Federal Rural de Pernambuco Reitor: Prof. Valmar Corrêa de Andrade Vice-Reitor: Prof. Reginaldo Barros Pró-Reitor de Administração: Prof. Francisco Fernando Ramos Carvalho Pró-Reitor de Extensão: Prof. Paulo Donizeti Siepierski Pró-Reitor de Pesquisa e Pós-Graduação: Prof. Fernando José Freire Pró-Reitor de Planejamento: Prof. Rinaldo Luiz Caraciolo Ferreira Pró-Reitora de Ensino de Graduação: Profª. Maria José de Sena Coordenação Geral de Ensino a Distância: Profª Marizete Silva Santos Produção Gráfica e Editorial Capa e Editoração: Allyson Vila Nova, Rafael Lira, Italo Amorim e Gláucia Fagundes Revisão Ortográfica: Marcelo Melo Ilustrações: Allyson Vila Nova Coordenação de Produção: Marizete Silva Santos
  • 3. Sumário Apresentação................................................................................................................. 4 Conhecendo o Volume 1 ................................................................................................ 5 Capítulo 1 – Introdução a Orientação a Objetos ............................................................. 7 1. Introdução ...................................................................................................................7 2. Evolução das Linguagens de Programação ..................................................................8 3. Paradigmas de Programação .....................................................................................10 Capítulo 2 – Orientação a Objetos: conceitos principais ............................................... 22 1. Introdução .................................................................................................................22 2. Abstração ...................................................................................................................23 Capítulo 3 – A Linguagem Java ..................................................................................... 37 1. Introdução .................................................................................................................37 2. Características da Linguagem ....................................................................................38 3. Máquina Virtual Java: o alcance de portabilidade .....................................................39 4. Codificando um primeiro programa Java ...................................................................40 5. JSDK – Java Software Development Kit ......................................................................42 6. JCreator: Ambiente de programação de iniciantes ....................................................44 Conheça o Autor .......................................................................................................... 50
  • 4. Apresentação Caro(a) Cursista, Seja bem-vindo(a) ao curso de Programação II. Este curso é composto por 4 volumes. Neste primeiro volume, vamos estudar a teoria e os principais conceitos relacionados ao paradigma de programação baseado em objetos. Além de apresentar suas vantagens em relação a outros paradigmas de programação, será também apresentada a linguagem de programação Java, a ser utilizada no curso para atividades práticas, como exemplos e exercícios. O segundo volume é dedicado em sua totalidade à sintaxe Java, seu sistema de tipos, operadores lógicos, comandos de decisão e repetição. No terceiro volume você aprenderá a utilizar os conceitos de orientação a objetos utilizando a sintaxe apresentada no volume anterior. Por fim, no quarto e último volume serão abordados assuntos ainda mais avançados, como a ideia de herança, polimorfismo e tratamento de exceções. Bons estudos! Fernando Trinta Professor Autor 4
  • 5. Programação II Conhecendo o Volume 1 Neste primeiro volume, você irá encontrar o Módulo 1 da disciplina Programação II. Para facilitar seus estudos, veja a organização deste primeiro módulo. Módulo 1 - Uma Introdução ao Paradigma Orientado a Objetos Carga Horária do Módulo 1: 15 h Objetivo do Módulo 1: Introduzir o paradigma de programação orientada a objetos, a partir de um histórico evolutivo dos paradigmas de programação, ressaltando seus benefícios em relação aos demais. Apresentar os principais conceitos do paradigma orientado a objetos. Introduzir a linguagem de programação orientada a objetos Java, que será utilizada no curso para utilização prática da teoria explanada. Conteúdo Programático do Módulo 1 » Introdução (Evolução dos paradigmas computacionais. O problema da complexidade. A ideia da abstração. Uma nova forma de encarar o problema: Objetos. Vantagens.) » Conceitos Fundamentais do Paradigma OO (Objetos. Classes. Métodos. Atributos. Mensagens. Polimorfismo. Herança.) » A linguagem de Programação Java (Histórico. Estrutura do código em Java. Compilação. Execução. O método main(). Escrevendo na tela. Independência de Plataforma/Máquina Virtual. Ambientes de programação. 5
  • 6. Programação II Capítulo 1 O que vamos estudar neste capítulo? Neste capítulo, vamos estudar os seguintes temas: » Introdução ao Paradigma Orientado a Objetos. » Evolução dos paradigmas computacionais. » O problema da complexidade. » A ideia da abstração. » Uma nova forma de encarar o problema: Objetos. » Vantagens e Desvantagens do Paradigma Orientado a Objetos. Metas Após o estudo deste capítulo, esperamos que você consiga: » Identificar as principais características do paradigma de programação orientado a objetos. » Descrever as vantagens do paradigma orientado a objetos em relação aos demais paradigmas. 6
  • 7. Programação II Capítulo 1 – Introdução a Orientação a Objetos Vamos conversar sobre o assunto? Caro(a) Cursista, é indiscutível o papel que a tecnologia da informação tem hoje na sociedade moderna. Praticamente toda a economia mundial está fortemente ligada a sistemas computacionais que gerenciam bancos, sistemas comerciais, órgãos públicos, dentre outros. Você alguma vez parou para pensar em como estes sistemas foram e continuam sendo construídos?! Não?! Então é hora de você começar a refletir sobre como se dá o processo de construção dos programas que realizam boa parte dos complexos sistemas computacionais modernos. E para isto, nós vamos abordar neste volume um pouco sobre o modelo de programação mais difundido atualmente, o paradigma baseado em objetos. Vamos lá? 1. Introdução Nas últimas décadas, a sociedade moderna vem cada vez mais sendo influenciada por sistemas de informação baseados em computador. Desde sistemas de comércio eletrônico, passando por jogos de computador e chegando até complexos sistemas militares, o mundo moderno é cada vez mais refém da tecnologia e dos sistemas de informação. Você consegue se imaginar em um mundo hoje sem computadores? Sem Internet? É difícil de imaginar. Este parece ser um caminho sem volta que fica ainda mais visível ao passo que nos últimos anos têm crescido o uso de aplicações em dispositivos móveis, como celulares, uso de novas aplicações baseadas em tecnologias inovadoras, como GPS, dentre outros. É inegável que as possibilidades do uso de novas tecnologias são importantes facilitadores para a vida moderna, como no caso de você querer utilizar o seu celular para, baseado na sua atual localização, descobrir qual a farmácia mais próxima ou o melhor caminho para chegar a determinado lugar. Porém, do ponto de vista de quem constrói os novos sistemas, isso tem se tornado um pesadelo, uma vez aumenta a complexidade destas aplicações. Construir as aplicações atuais requer uma série de passos que ajudem a tratar a complexidade destes sistemas. Estes passos e as pessoas que são envolvidas no desenvolvimento de sistemas criaram uma disciplina, conhecida hoje como Engenharia de Software. Esta disciplina ou processo de desenvolvimento concentra as atividades de entender o que um sistema deve fazer (análise), propor uma solução computacional (projeto) e desenvolver esta solução (implementar/codificar) (Figura 1). Esta última fase está diretamente relacionada ao tema desta disciplina: criar aplicações a partir de uma linguagem de programação. Figura 1 – Processo Resumido de Desenvolvimento de Aplicações 7
  • 8. Programação II A ideia de codificar representa uma forma de escrever por meio de uma linguagem de programação, o projeto da solução proposta nas fases anteriores da engenharia de software. Informalmente, uma linguagem de programação pode ser definida como um conjunto limitado de instruções (vocabulário), associado a um conjunto de regras (sintaxe) que define como as instruções podem ser associadas. Ou seja, como se pode compor os programas para a resolução de um determinado problema. Os programas escritos em uma linguagem de programação são então traduzidos para uma linguagem de máquina, que é compreendida pelo computador. O resultado desta conversão são programas executáveis que realizam uma série de ações, como solicitar dados, realizar cálculos específicos ou apresentar dados para usuários. Ao longo dos anos, foram desenvolvidas (e continuam sendo) uma grande quantidade de linguagens de programação, algumas de uso mais geral e outras concebidas para áreas de aplicação específicas. Porém, apesar de suas diferenças, estas linguagens são geralmente agrupadas de acordo com as características principais que indicam como um programador (quem escreve o programa) enxerga a forma de organizar os programas. As diferentes maneiras como uma linguagem organiza seus conceitos é chamada de paradigma de programação. Dentre alguns dos mais conhecidos paradigmas de programação podem- se citar: paradigma imperativo, paradigma estruturado e o paradigma orientado a objetos. A tabela a seguir indica o índice de popularidade dos principais paradigmas de programação existentes: Tabela 1 – Distribuição de Paradigmas segundo índice de popularidade [Fonte: http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html] Paradigma Indice de Popularidade Orientado a Objetos 54,6% Procedural 41,5% Funcional 2,8% Lógico 1,1% Neste momento, caro(a) cursista, você pode se perguntar: para que diferentes paradigmas? Para responder esta questão é necessário voltar no tempo e entender como as linguagens de programação evoluíram ao longo dos anos. 2. Evolução das Linguagens de Programação 2.1. A linguagem de máquina e a linguagem montadora Um computador é organizado em um conjunto de circuitos eletrônicos. Desta forma, seu controle é feito ainda através de uma forma bem primitiva, baseado em um sistema binário para representação de dados e operações. Esta representação é chamada de código binário ou linguagem de máquina, por ser compreendida e executada no hardware do computador. Esta linguagem consiste de uma grande sequência de números (1s e 0s), que instruem os computadores a realizar suas operações mais elementares, uma de cada vez. A figura a seguir apresenta um trecho de um possível programa em linguagem de máquina. 8
  • 9. Programação II Figura 2 – Código de Máquina Criar programas em código binário é impraticável. Para facilitar a construção dos programas, uma nova linguagem de programação foi proposta, onde eram utilizadas abreviações para representar as operações elementares. As linguagens que seguiram esta estratégia foram chamadas linguagens montadoras ou assembly. Em Assembly, em vez de números binários, utiliza-se palavras abreviadas, chamadas também de mnemônicos, indicando a operação a ser realizada. Estas linguagens estavam mais próximas do entendimento dos humanos, e através de um programa chamado montador, o código binário era gerado e podia a ser executado nos computadores da época. Abaixo são apresentados dois exemplos de instruções Assembly: » MOV R1, R2 – A instrução MOV (abreviatura do termo em inglês MOVE) recebe como parâmetros, dois registradores: R1 e R2. Sua execução determina a cópia do conteúdo de R2 para R1 (equivalente R1:=R2, sendo R1 e R2 equivalente a duas variáveis); » ADD R1, R2 – A instrução ADD (abreviatura de ADDITION) recebe como parâmetro, dois registradores como parâmetros: R1 e R2. Sua execução adiciona o conteúdo de R1 ao de R2 e o resultado é armazenado em R1 (equivalente à instrução Pascal R1:=R1+R2). Utilizando estes comandos, os programadores utilizaram Assembly para realizar seus programas. Por exemplo, para somar dois inteiros, um programa em Assembly poderia ser escrito através da rotina descrita abaixo. MOV AX,B ; registro AX recebe o valor de memória contida na variável B ADD AX,C ; AX recebe a soma de AX (valor de B) com o valor de C MOV A,AX ; variável A recebe valor de AX Dá para verificar que o mesmo ainda está bem próximo da linguagem da máquina que do homem. Difícil de entender!? Bastante! Porém, isso na época permitiu que se facilitasse a forma de se construir os programas de computador. 2.2. Aumentando o nível de abstração das linguagens O uso dos computadores foi se popularizando. Com isso, novas aplicações foram propostas para os computadores que surgiram. Com isso, tornou-se necessário facilitar ainda mais a forma como os programas de computadores eram escritos. Surgiram então as chamadas linguagens de programação de alto nível, onde uma única instrução poderia ser utilizada para realizar várias operações elementares do computador. Um programa tradutor chamado compilador transformava o código em alto nível em linguagem de máquina. Programas passaram a ser escritos em uma linguagem mais próxima da linguagem natural e utilizavam notações matemáticas semelhantes ao cotidiano das pessoas. Um programa para calcular o fatorial de um número poderia ser escrito como na figura a seguir. 9
  • 10. Programação II int fatorial(int n) { if (n == 0) return 1; else{ fat = 1; for (int i=2:i<=n){ fat = fat * i; } return fat; } } Figura 3 – Trecho de um programa para cálculo de um fatorial escrito na linguagem C Se mesmo para você esta versão em uma linguagem de alto nível ainda seja incompreensível, pelo menos se percebe que são utilizados menos construções para se realizar a mesma tarefa que em uma linguagem montadora. Desta forma, os programas ficaram mais fáceis de serem compreendidos por nós, humanos. Isto facilitou bastante a programação e, principalmente, a manutenção e correção de erros nos programas. Várias foram as linguagens de alto nível propostas. Dentre algumas, pode-se citar Fortran, Pascal, Basic e C. Algumas delas são bem populares ainda hoje. O surgimento das linguagens de alto nível auxiliou programadores a construir programas mais enxutos, mas fáceis de compreender e também de corrigir erros... Mas onde está o conceito de paradigma nesta história?! Vamos lá então... 3. Paradigmas de Programação 3.1. Paradigma Imperativo Como vimos anteriormente, um paradigma de programação explica como elementos que compõem um programa são organizados e interagem entre si. No caso das linguagens montadoras ou das linguagens de alto nível, a construção dos programas é realizada através de instruções que indicam o que o computador deve realizar. A diferença é que para linguagens montadoras, o programador precisava ser muito mais detalhista que em uma linguagem de alto nível. Um simples comando na linguagem C era equivalente a dezenas de linhas em uma linguagem de baixo nível. Porém, a ideia era a mesma: um conjunto de instruções que ilustram uma estratégia de um ser humano em “COMO” resolver um problema. Esta forma de organizar os programas estabelece um primeiro paradigma de programação conhecido: o paradigma imperativo. Programar um computador neste paradigma significa “dar-lhe ordens” que são executadas sequencialmente. O paradigma imperativo é profundamente influenciado pela arquitetura como os próprios computadores são organizados, a arquitetura de von Neumann. Neste modelo, você deve pensar em um programa como um computador que tem memória que guarda um estado por meio de 10
  • 11. Programação II dados (variáveis), e que recebe instruções que modificam e apresentam estes dados, como ilustrado na figura a seguir: Figura 4 – Modelo Imperativo de programação Como todas as arquiteturas de computadores existentes hoje se baseiam na arquitetura de Von Neumann, os ambientes de execução das linguagens imperativas são bastante eficientes. Porém, mesmo assim, programas escritos no paradigma imperativo ainda são muito detalhistas, o que requer um grande esforço na construção e, principalmente, na manutenção dos programas. Conforme a complexidade dos programas aumenta, a legibilidade, ou seja, a facilidade com que os programas podem ser lidos e entendidos, torna-se também mais difícil. Com isso, a manutenção continuou sendo um problema, e erros acabavam sendo introduzidos sem querer durante o processo de depuração (correção) de programas. 3.2. Paradigma Procedural Uma evolução do paradigma imperativo foi a percepção que certas sequencias de instruções que são repetidas em vários pontos de um mesmo programa. Estes sequências de passos poderiam ser agrupadas em procedimentos e funções (também chamados de sub- rotinas) definidas pelo programador e serem chamadas de diversos pontos do programa, como no caso de criarmos uma função que calcule o valor do fatorial de número (Figura 5). Por esta característica, o paradigma imperativo também é conhecido na literatura como o paradigma procedural. Figura 5 – Paradigma Imperativo VS Paradigma Procedural O paradigma procedural foi durante muitos anos o padrão para linguagens de programação. Este paradigma acabou influenciando também a forma como a própria análise e projeto das aplicações eram realizados. O paradigma procedural induzia que sistemas mais complexos precisavam ser “quebrados” em partes menores, mas fáceis de lidar. Este princípio de “dividir para conquistar” é a abordagem padrão que os desenvolvedores de sistemas utilizam para lidar com sistemas complexos. No caso do paradigma procedural, o sistema era dividido em muitas funções que representavam as diversas funcionalidades que o programa tinha que fazer. Isso era 11
  • 12. Programação II repetido até se chegar a um nível que as funções eram claras o suficiente para entender seu funcionamento, ou mesmo para serem reaproveitadas em diferentes pontos de um programa. Com procedimentos, funções menores eram mais fáceis de entender, além de facilitar eventuais correções de um programa, em caso de erros. De certa forma, esta abordagem de lidar com a complexidade também lida com um conceito chave para a construção de sistemas e a programação de aplicações: a abstração. A ideia de abstração faz com que os desenvolvedores concentrem seus esforços no que é relevante, deixando detalhes irrelevantes para serem tratados mais tarde. Abstração dentro de um paradigma de programação indica como os problemas são encarados. Os conceitos utilizados para resolver estes problemas são as abstrações utilizadas por um paradigma. No caso do paradigma procedural, as abstrações utilizadas para decompor um problema complexo são as sub-rotinas (funções e/ou procedimentos). O uso de sub-rotinas separa dados (variáveis) e operações (procedimentos) sobre os dados, onde a ideia de funções e procedimentos manipulando um conjunto de dados surgiu como um modelo natural para representar como as aplicações. Porém, esta abordagem também apresenta seus problemas. Primeiro, o caminho de execução do programa ficou mais complexo devido à chamada de funções e procedimentos em diversas partes do código. A confusão de chamadas e desvios era tão grande que se criou um termo específico para os programas mal-estruturados a partir de várias chamadas de sub-rotinas, o “código espaguete” (Figura 6). Figura 6 – O código espaguete [Fonte: http://www.yourdictionary.com/images/computer/SPAGETI.GIF] No entanto, o maior problema está relacionado com a separação de dados e procedimentos, pois várias partes de um mesmo programa podiam alterar os valores de variáveis compartilhadas. Em muitos casos, a modificação de uma variável por uma sub-rotina causava a falha na execução de outra sub-rotina que dependia do valor da mesma variável. 12
  • 13. Programação II Além disso, como procedimentos utilizavam valores em variáveis separadas, uma alteração na representação de uma variável poderia exigir uma alteração em cascata em todas as sub- rotinas que dependessem deste valor. Ou seja, um pesadelo para o programador! Figura 7 – Relação entre dados e procedimentos no paradigma procedural Vejamos isso em exemplo mais claro, como o cálculo de uma folha de pagamento de uma empresa. Neste caso, os dados relativos a cada um dos funcionários ficariam espalhados no programa. Seria necessário recuperar estes dados para cada funcionário obter e então realizar o processamento do cálculo da folha de pagamento (Figura 8). Este processamento seria representado por uma função ou uma sub-rotina. Figura 8 – Cálculo de uma folha de pagamento no paradigma procedural Com o aumento da complexidade das aplicações, o gerenciamento entre procedimentos e dados dispersos criava um pesadelo para os programadores que precisavam realizar manutenções no sistema. Modificações em um dado poderiam desencadear um processo de atualização em vários procedimentos. Figura 9 – Dificuldade do gerenciamento de dados e procedimentos no paradigma procedural Além disso, verificou-se que ao longo dos anos, os procedimentos mudavam muito mais que os dados manipulados. Como exemplo, as regras que podem ser associadas ao cálculo do salário de um funcionário variam muito mais que os dados do funcionário, como seu nome ou seu cargo. Desta forma, era necessária uma nova forma de organizar os sistemas. 13
  • 14. Programação II 3.3 Programação Modular e Estruturada Para tentar melhorar as deficiências do paradigma procedural, surgiu então a programação modular. Nesta abordagem, o programa é dividido em vários componentes ou módulos. Ao contrário do paradigma procedural, módulos combinam dados e procedimentos. Um módulo é composto de dados que são manipulados pelos procedimentos deste módulo. Cada módulo fornece um conjunto de procedimentos para que outras partes de um programa possam acessar dados internos de um módulo. Este conjunto de procedimentos ou funções é conhecido como interface do módulo. Desta forma, dados internos de um módulo são protegidos contra manipulações indevidas de outros módulos, em um princípio conhecido como encapsulamento. Estas características trouxeram vantagens em relação aos seus predecessores. Dentre algumas, pode-se citar: » Estrutura do programa fica mais clara ao agrupar funções e variáveis relacionadas em um mesmo módulo; » Possibilidade de alterar módulos separadamente. Uma vez que cada módulo preserve sua interface visualizada por outros módulos, modificações internas e novos procedimentos podem ser incluídos; » O acesso a dados internos de um módulo é feito através de sua interface. Com isso, tem-se um maior controle sobre operações indevidas sobre estes dados. Por exemplo, é possível verificar se um dado pode ou não ser modificado para um determinado valor, antes de se efetivar a mudança. Este estilo de programação também muito referenciada como programação estruturada, devido a uma melhor organização dos conceitos utilizados nos programas. A programação estruturada tornou-se um sucesso e, a partir de seus conceitos, métodos de modelagem e análise foram propostos para facilitar o projeto das novas aplicações que surgiam na época em que surgiu a programação estruturada, como a Análise Estruturada de Tom DeMarco, e a Análise Estruturada Moderna, de Edward Yourdon. Com as ideias de módulos, encapsulamento e interfaces, a programação modular permitiu um melhor aproveitamento e distribuição de programas. Os módulos construídos por um programador poderiam ser reaproveitados por outros programadores, sem a necessidade de se entregar código-fonte. Bastava que os programadores que desejassem utilizar um módulo soubesse a interface deste módulo. Imagine um módulo como uma biblioteca de funções. Poderia haver um módulo para fazer, por exemplo, a verificação se um CPF é válido ou não. A única coisa que um programador precisaria saber é que este módulo possui uma função chamada valida_cpf, que recebe como parâmetro um número de 11 dígitos e retorna verdadeiro se este número representa um CPF válido. Para os programadores que vão utilizar o módulo, ele é considerado uma caixa-preta, no sentido que não se sabe como ele funciona internamente. O importante é que ele forneça o resultado que se espera dele. Porém, a programação modular também apresenta seus problemas. O primeiro e principal problema é o fato que módulos não eram naturalmente extensíveis. Isso significava que para fazer alterações em módulo, era necessário entrar no código-fonte e diretamente realizar as modificações. E em muitas situações, se via a necessidade de criar novas funcionalidades dos programas a partir de módulos já existentes. 14
  • 15. Programação II 3.4. O Paradigma Orientado a Objetos O termo “programação orientada a objetos” foi criado por Alan Kay (imagem ao lado), autor da linguagem Smalltalk. Sua proposta visa aproximar a maneira como construímos os programas de computador do mundo real. O mundo real é composto por entidades que interagem, que trocam serviços entre si para realizar suas tarefas. Na proposta de orientação a objetos, estas entidades são chamadas objetos. Objetos podem representar tanto entidades concretas (como uma pessoa ou um livro) quanto entidades abstratas (como uma transação bancária ou uma sessão de um usuário ao acessar um site). Para identificar objetos são empregadas técnicas que os próprios seres humanos utilizam para organizar seus pensamentos, como classificação de elementos, diferenciação entre parte e todo, troca de mensagens, dentre outros. Alan Kay utilizou uma analogia com um sistema molecular, batizada então de “analogia biológica”. Nesta proposta, ele se questionou: “como seria um sistema de computador que se organizasse como um ser vivo?”. Sua proposta estabelecia que: » O sistema seria organizado em células, onde cada célula se comportaria como uma unidade autônoma; » Cada “célula” interagiria com outras células através do envio de mensagens para realizar um objetivo comum; Para Kay, objetos do mundo real também se comportam como estas células. A partir de sua analogia biológica, ele estabeleceu os princípios básicos para a orientação a objetos. São estes: 1. Qualquer coisa é um objeto; 2. Objetos realizam tarefas através da requisição de serviços a outros objetos; 3. Cada objeto pertence a uma determinada classe. Uma classe agrupa objetos similares; 4. A classe é um repositório para comportamento associado ao objeto; 5. Classes são organizadas em hierarquias. 3.4.1. Estabelecendo um exemplo Para melhorar sua compreensão, vamos utilizar um exemplo prático. Imagine a situação em que um cliente chamado Ian deseja comprar uma pizza via um serviço de entrega em domicílio. Ian interage com uma atendente (Maria) e faz sua solicitação. Maria por sua vez interage com Mário, o pizzaiolo, repassando a solicitação de Ian, uma vez que quem sabe fazer a pizza é Mário, afinal ele é o pizzaiolo. Após a pizza ficar pronta, ela é entregue ao Zé, o motoboy, que tem por função entregar a pizza a Ian e receber o pagamento. A Figura 10 ilustra a interação entre estes personagens. 15
  • 16. Programação II Figura 10 – Um exemplo para a orientação a objetos na vida real Embora o exemplo acima ainda possa ser refinado e inserir ainda mais participantes, ele é suficiente para ilustrar os conceitos propostos pelo paradigma orientado a objetos. Primeiramente, cada elemento que participa do processo é considerado um objeto. Cada objeto é uma entidade única no sistema. No caso temos Ian, Maria, Mário e Zé como objetos. Não existem duas “Marias”. Poderiam até existir duas funcionárias com o mesmo nome, mas não seriam a mesma pessoa. Cada objeto tem dados ou propriedades que os identificam. No caso, cada pessoa no processo tem um nome. Cada objeto interage com os demais por meio da solicitação de serviços. No caso, Ian solicita seu pedido através da atendente Maria, que lhe fornece os produtos que ela pode entregar a Ian. De forma semelhante, Maria solicita a Mário a pizza escolhida por Ian, passando informações necessárias para realização deste serviço, como o sabor da pizza e o tipo da borda, como ilustrado na Figura 11. Figura 11 – Solicitação de um serviço através da troca de mensagem entre objetos Seguindo sua análise, cada objeto pertence a uma determinada classe que agrupa objetos similares. No nosso exemplo, a pizzaria não atende apenas ao cliente Ian. Podem existir outras dezenas de clientes que também podem fazer seus pedidos à Pizzaria. Estes clientes possuem características comuns, como um cadastro na loja ou um endereço de 16
  • 17. Programação II entrega. Obviamente, para cada cliente, os valores associados a estas propriedades são, em geral, diferentes. Estes objetos são tratados e agrupados como um tipo único de objeto, uma classe. Neste caso, poderíamos agrupar Ian, Cris e Evandro como objetos da classe Cliente, como ilustrado na Figura 12. Figura 12 – Objetos de uma mesma classe Por fim, classes são organizadas em hierarquias. No nosso exemplo, Maria, Mário e Zé poderiam ser agrupados em uma classe que representem os funcionários da Pizzaria (Figura 13). Estes possuem características comuns como um salário, um horário de trabalho. Porém, estes também poderiam ser classificados como pessoas, com atributos como nome, sexo, dentre outros. Neste caso, a classe Pessoa englobaria tanto funcionários quanto clientes, indicando que existem certas propriedades comuns, como o fato de tanto clientes quanto funcionários possuírem um nome. Figura 13 – Hierarquias de classes de objetos Mas vistos estes conceitos, em que a orientação a objetos pode melhorar a forma como programamos nossas aplicações? Para isso, vamos pegar o exemplo do cálculo de uma folha de pagamento de uma empresa, como ilustrado na Figura 14. Figura 14 – Uma folha de pagamento no modelo estruturado 17
  • 18. Programação II Relembrando: como os dados e funções são separados, calcular o custo total da folha requer que saibamos individualmente todos os dados de cada funcionário, o que acabava por fazer com que a evolução do sistema ficasse bastante complicada. Agora veja como seria uma possível versão utilizando a abordagem orientada a objetos (Figura 15). Figura 15 – Uma folha de pagamento no modelo de objetos Nesta versão, cada funcionário é representado por um objeto. Um objeto atua como um módulo que engloba dados, e também fornece operações que manipulam tais dados. Os dados internos de cada objeto são chamados atributos, enquanto as operações que um objeto fornece são chamados de métodos. No caso, todo objeto que representa um funcionário possui como atributos seu nome, seu cargo, seu salário fixo e uma série de outros atributos que são comuns a qualquer funcionário da empresa. Para se calcular seu salário, cada funcionário oferece um método chamado calculaSalario, que internamente utiliza os dados de cada objeto e fornece o valor de seu salário individual. Para calcular o custo total da folha de pagamento seria então somar os valores obtidos pela chamada de cada método calculaSalario, em cada objeto que representa um funcionário da empresa. A orientação a objetos representa uma nova forma de enxergar e modelar o mundo como um conjunto de objetos inter-relacionados, interagindo por meio da troca de mensagens. A abstração escolhida (objeto) combina estrutura de dados e comportamento funcional, fazendo com que os dados sejam preservados e procedimentos modificados mais facilmente, sem causar impactos tão profundos quanto o paradigma estruturado. A ocorrência de erros ou alterações vão estar associadas a um único módulo ou a um pequeno grupo deles, onde é mais fácil depurar e isolar erros. Esta forma de organizar os programas cria um modelo mais intuitivo e fácil de usar, mas principalmente, aumenta a possibilidade de reuso entre objetos. Objetos podem ser criados a partir de outros objetos. Por exemplo, você poderia criar um objeto que representasse um funcionário diferenciado, como aquele cujo salário fosse baseado em comissões, e não em um salário fixo. Este objeto poderia ser criado através de um mecanismo especial de extensão chamado Herança. Resumidamente, este novo objeto teria as mesmas características de um funcionário comum, mas poderia ter dados a mais, assim como seus métodos poderiam ser modificados, como no caso de seu salário. 3.5. Programação Orientada a Objetos VS Programação Estruturada A forma de organizar um programa usando orientação a objetos é essencialmente diferente do desenvolvimento tradicional de software. Mesmo assim, alguns conceitos do modelo orientado a objetos podem ser equiparados a conceitos do modelo estruturado, 18
  • 19. Programação II como visto na figura a seguir. Figura 16 – Paradigma orientado a objeto VS Paradigma Estruturado A programação orientada a objetos é especialmente útil à medida que os sistemas tornam-se cada vez mais complexos, e por consequência, seus programas ficam cada vez maiores. Grandes programas se beneficiam mais com a modularidade oferecida por objetos. Dividindo o programa em vários módulos independentes (objetos), aumenta-se a flexibilidade e a facilidade para manutenção do programa como um todo. Na programação estruturada, a reusabilidade é limitada a trechos de algoritmos representados por meio de sub-rotinas. Na programação orientada a objeto é possível reutilizar todo um módulo, no caso o objeto, com seus métodos e seus atributos. Em geral, a programação orientada a objetos ainda apresenta como vantagens: código mais lógico, e melhor encapsulado, uma maior facilidade de manutenção e extensão do código, um melhor reaproveitamento de código, dentre outros. Como desvantagens, pode-se afirmar que o aprendizado de uma linguagem orientada a objetos é mais complexo, principalmente para aqueles já familiarizados com o paradigma estruturado. É necessário mudar a forma de pensar na solução de um programa, utilizando conceitos não tão simples quanto do paradigma estruturado. Por fim, dificilmente uma linguagem orientada a objetos conseguirá ter um desempenho em tempo de execução superior a linguagens não orientadas a objetos. Exercícios 1. Com suas palavras conceitue: (a) linguagem de programação e (b) paradigma de programação. 2. Utilizando a Internet, verifique quais são os outros paradigmas de programação existentes além dos apresentados neste capítulo. Explique qual o propósito de pelo menos dois outros paradigmas. 3. Em sua opinião, ainda faz sentido hoje se programar em uma linguagem de baixo nível como Assembly?! Justifique sua resposta. 4. Para muitos pesquisadores, o paradigma orientado a objetos é apenas uma extensão do paradigma estruturado. Você concorda ou discorda desta opinião? Justifique. 5. Utilizando a abordagem de uma programação estruturada, resolva o seguinte problema. É necessário descobrir o atleta que mais marcou gols em um campeonato de futebol. Descreva (em português ou em linguagem de programação que você conheça) como seria solução deste problema. 6. Utilizando o mesmo problema da questão anterior, como seria a solução utilizando 19
  • 20. Programação II objetos. Minibiografia Edsger Wybe Dijkstra (11 de Maio de 1930 — 6 de Agosto de 2002) foi um pesquisador holandês mundialmente conhecido por suas contribuições nas áreas de desenvolvimento de algoritmos e programas de linguagens de programação. Foi o precursor da ideia contrária ao uso de comandos “GOTO” em linguagens de programação, um recurso muito utilizado na sua época. Em seu artigo “A Case against the GO TO Statement”, Dijkstra alertou para vários erros decorrentes do uso da declaração GOTO. Uma transcrição deste artigo pode ser visto na URL: http://www.cs.utexas. edu/~EWD/transcriptions/EWD02xx/EWD215.html. Suas pesquisas impulsionaram o surgimento da programação estruturada.Em 1972, recebeu o Prêmio Turing por suas contribuições com o ALGOL e no campo de linguagens de programação. Vamos Revisar? Você estudou, neste capítulo, como as linguagens de programação evoluíram ao longo dos anos no intuito de facilitar a vida dos programadores das aplicações modernas. Esta evolução foi motivada principalmente pela crescente complexidade dos programas. Com isso, as linguagens têm focado principalmente em criar abstrações que melhorem a compreensão e manutenção destes programas. Você também viu que é possível classificar as linguagens em grupos que seguem o mesmo conjunto de ideias sobre a estruturação e execução de um programa, os chamados paradigmas de programação. Desde o paradigma imperativo até o paradigma estruturado, vários foram os avanços na estruturação dos programas, como a reutilização através de sub-rotinas até o uso de módulos autocontidos que protegem seus dados de acesso indevido. Apesar destas evoluções, havia muito o que evoluir, principalmente no que diz respeito ao reuso dos programas. Para isso, uma nova abordagem de programar foi proposta: a orientação a objetos. Neste novo paradigma, programas se aproximam mais do mundo, através de objetos que interagem para a realização de uma tarefa. No próximo capítulo, você verá com mais detalhes os principais conceitos deste novo paradigma. 20
  • 21. Programação II Capítulo 2 O que vamos estudar neste capítulo? Neste capítulo, vamos estudar os seguintes temas: » Conceitos fundamentais do paradigma orientado a objetos, como: › Classes, Objetos, Atributos e Métodos. › Abstração. › Encapsulamento. › Polimorfismo. › Herança. Metas Após o estudo deste capítulo, esperamos que você consiga: » Descrever os principais conceitos utilizados no paradigma orientado a objetos. 21
  • 22. Programação II Capítulo 2 – Orientação a Objetos: conceitos principais Vamos conversar sobre o assunto? No capítulo anterior, você viu que ao longo dos anos a programação buscou uma constante evolução no intuito de facilitar a vida dos programadores. O progresso na organização dos programas evoluiu. Porém, os sistemas também ficaram cada vez mais complexos. Em particular, os paradigmas de programação até então falhavam principalmente em relação à reutilização de código. Para enfrentar este problema, um novo paradigma surgiu: a orientação a objetos. Vamos abordar neste capítulo os principais conceitos relacionados a esta nova forma de organizar seus programas. Este capítulo é fundamental para seu bom progresso no curso. Então, vamos aprender? 1. Introdução Como vimos no capítulo anterior, a programação orientada a objetos surgiu como uma nova abordagem para tratar a inerente complexidade dos novos sistemas. A programação orientada ao objeto (object-oriented programming) pode ser considerada como uma extensão quase natural da programação modular. Apesar de seus conceitos já terem sido estabelecidos desde a década de 70, apenas em meados da década de 90 que este paradigma começou a ganhar maior destaque na comunidade de desenvolvimento de sistemas. Seu uso enfatizou uma ideia que até então passava despercebida: a aproximação com o mundo real. Na programação orientada a objetos temos a necessidade de buscar as entidades de um domínio, onde através da qual um indivíduo observa a realidade (domínio) e procura capturar sua estrutura (abstrair entidades, ações, relacionamentos) com elementos que forem considerados relevantes para a descrição desse domínio. Com as entidades de domínio identificadas, podemos utilizar as técnicas de abstração para a composição das classes abstratas, construindo desta maneira um sistema facilmente reutilizável nas suas estruturas internas. A abordagem OO (orientada a objetos) enfatiza duas características: (i) reutilização de código e (ii) modularidade. Nisto, OO é imbatível quando comparada com as metodologias antigas. Em termos de modelo computacional podemos dizer que enquanto as metodologias tradicionais utilizam o conceito de um processador, uma memória e dispositivos de I/O para processar, armazenar e exibir as informações. A orientação a objetos emprega um conceito mais real, mais concreto: o de Objeto. Porém, além de objetos, existe uma série de outros conceitos que são importantes para a compreensão do paradigma OO, representados na Figura 17. São eles: encapsulamento, polimorfismo, herança, composição e abstração. 22
  • 23. Programação II Figura 17 – Os pilares do paradigma orientado a objetos Vamos dar uma olhada agora como cada um destes conceitos contribui no paradigma OO. 2. Abstração Abstração é considerada a habilidade de modelar características do mundo real do problema que o programador esteja tentando resolver. Ao mesmo tempo, para melhor lidar com a modelagem de problemas complexos, este processo mental indica que se deve ignorar detalhes não relevantes e focar nas características essenciais dos elementos modelados. Com isso, uma realidade complexa pode ser representada em um modelo simplificado, como os objetos no paradigma OO. A abstração na descrição de objetos depende do ponto de vista e objetivo de quem faz a descrição. Grady Booch, um atuante e renomado pesquisador na comunidade científica, ilustra esta observação na sua frase: “Uma abstração depende mais do observador do que do objeto observado”. Por exemplo, a visão de um apartamento por um engenheiro civil tende a ser diferente da de um decorador de ambientes. O primeiro deve se preocupar mais com os aspectos relacionados ao posicionamento de vigas de sustentação, colunas, dentre outros. Já um arquiteto se preocuparia mais em como otimizar o espaço, maximizar a circulação de ar, do melhor local para colocar mesas e cadeiras. Estas diferentes visões ocorrem pelo diferente interesse que os dois profissionais tem sobre a mesma entidade observada: o apartamento. O mesmo vale para a programação, pois só devemos representar nos sistemas que vamos criar, aquelas características que nos interessam dos objetos reais. Como exemplo, ao modelarmos um objeto avião no contexto de um sistema de venda de passagens aéreas, não vai nos interessar a característica do número de turbinas do avião, mas sim, seu número de assentos disponível. Existe uma série de princípios que são utilizados por nós, humanos, para realizar abstrações em nosso cotidiano. Vamos ver como alguns destes princípios e como eles se aplicam no paradigma OO. 2.1. Classificação/Instanciação Classificação é um mecanismo de abstração através do qual o ser humano percebe a existência de um conjunto de fenômenos da realidade (elementos, interações) com algumas características em comum e atribui um nome (conceito) a esse conjunto (classe) de fenômenos. Já a instanciação é o processo inverso à classificação. Na orientação a objetos, este princípio é utilizado para a identificação de classes e objetos. As duas ações possíveis são: » Classificar significa agrupar objetos com base em estruturas e comportamentos semelhantes; 23
  • 24. Programação II » Instanciar objetos significa gerar novos exemplares a partir de uma descrição abstrata de um objeto genérico. Vejamos o exemplo na Figura 18, que ilustra estes processos no contexto de dois estudantes, João e Maria. Ambos são indivíduos, com seus dados particulares, como seus nomes. Porém, ambos podem ser agrupados no conjunto de indivíduos que representam os estudantes. Figura 18 – Classificação/Instanciação de objetos A “semântica” ou o significado do mecanismo de classificação equivale a um mecanismo de pertinência. Neste mecanismo, o fato de um objeto pertencer a uma determinada classe pode ser melhor caracterizado se ocorrer uma relação do tipo “é um / é uma”. Por exemplo, “Maria é uma estudante”. A partir desta abstração, pode-se então melhor entender os conceitos de objetos e classes, atributos e métodos. Objetos representam entidades do mundo real, quer sejam estas concretas ou abstratas, sobre as quais são armazenados dados e temos operações para manipulá-los. Objetos também se caracterizam por ter uma identidade única, um comportamento e um estado. A identificação de objeto deve ser única, uniforme e independente do conteúdo do objeto. Isso implica que podem haver objetos com características semelhantes (como dois martelos azuis ou dois funcionários com o mesmo nome), mas que são distintos. Uma classe é abstração das características mais importantes de um grupo de objetos semelhantes. Cada classe descreve um conjunto (possivelmente infinito) de objetos individuais. A partir de uma classe podem ser gerados diferentes objetos e por isso, cada objeto é dito ser uma instância de uma classe. Assim, cada instância de uma classe tem seus próprios valores para cada dado que o caracteriza, mas também podem compartilhar dados e comportamento com as outras instâncias da classe. Implicitamente, cada objeto contém uma referência para sua própria classe -- em outras palavras, ele sabe o que ele é. Existe hoje uma representação bastante difundida para representar graficamente classes em um modelo orientado a objetos. Esta notação é definida por uma linguagem visual chamada UML (do inglês, Unified Modeling Language). UML é utilizada para representação de muitas etapas durante a análise de um sistema. Ela é formada por vários diagramas. Um deles é o diagrama de classes, em que classes são representadas graficamente. Para facilitar nossa explicação sobre os conceitos OO, utilizaremos a notação UML para descrever as classes nesta disciplina. Em UML, uma classe é representada como descrito na figura a seguir. 24
  • 25. Programação II Figura 19 – Notação UML para Classes Nesta notação, há uma caixa retangular composta de três partes. A primeira parte (localizada no topo do retângulo) define o nome da classe. Esta é única parte que deve existir na notação UML para representar uma classe. A parte intermediária diz qual é a estrutura da classe. Enquanto a parte inferior informa qual é o seu comportamento, através das ações que objetos desta classe podem realizar. Para melhor exemplificar, a classe Estudante tem como estrutura interna o nome do estudante e o curso ao qual ele está vinculado. Como ações, é possível pedir para um objeto imprimir seu nome. Cada objeto possui um conjunto de características ou informações que os caracteriza, chamadas então de atributos. O conjunto de atributos também é chamado de estrutura da classe. Por exemplo, a classe Estudante pode conter como sua estrutura informações como o nome, sexo, data de nascimento, colégio ou faculdade, dentre outros. Os atributos possuem valores, funcionando como variáveis. Por exemplo, o atributo nome para um dos objetos da Figura 19 deve guardar o valor “João”. O conjunto de valores dos atributos de um determinado objeto é chamado de estado. Como visto na Figura 19, atributos (se existirem) são representados na parte intermediária de uma classe em UML. O comportamento de um objeto é definido através de seus métodos. Métodos definem as habilidades dos objetos. Em outras palavras, as ações que um objeto de uma classe pode realizar. É comum serem chamados também de comportamento de uma classe de objetos. Na maioria das vezes, métodos utilizam os atributos da classe como “matéria- prima” para realizar suas ações, além de também poderem receber parâmetros, como em um procedimento tradicional. Uma classe pode ter qualquer número de métodos, inclusive nenhum. Por exemplo, para uma classe carro, poderiam ser definidas ações como andar, frear, ligar o motor, dentre outras. Como visto na Figura 19, métodos (se existirem) são representados na parte inferior de uma classe em UML. Métodos são definidos nas classes, porém sua execução só ocorre quando o método é invocado através do objeto. Por exemplo, pode haver uma classe que represente um automóvel e dois objetos que representem dois modelos diferentes: um Fusca e uma Ferrari. A classe define um método, que faz com que a velocidade do automóvel seja reduzida. A utilização de um método frear() deve afetar apenas um objeto em particular. Todos os carros podem frear, mas a ação em um objeto afeta apenas o objeto em questão. Apesar da independência de cada objeto, para que um sistema funcione é necessário que os objetos interajam. A interação entre objetos ocorre através da troca de mensagens. Uma mensagem representa o ato de um objeto de uma classe chamar algum método que outro objeto possua, fazendo com que este comportamento seja executado. É comum esta ação ser chamada de ativação ou invocação de um método. Em analogia com a programação estruturada, uma mensagem pode ser vista como uma chamada a procedimento, inclusive com o retorno de um resultado a partir da execução deste método, como ilustrado na Figura 20. 25
  • 26. Programação II Figura 20 – Ilustração do envio de uma mensagem para um objeto Para um objeto invocar um método em outro objeto é necessário que obtenha uma referencia ao objeto-alvo. Como cada objeto precisa ser identificado de forma unívoca (ou seja, de forma exclusiva), faz-se então necessário definir um identificador para cada objeto. Tome como exemplo a Figura 21. A classe Estudante define as características gerais de um aluno. O método imprimirNome() é definido para apresentar tanto o nome do aluno, quanto seu curso. Figura 21 – Referências para objetos Existem dois objetos que representam dois alunos distintos. Para isso, cada objeto tem um identificador único. Para o aluno cujo nome é Fernando, o identificador do objeto é aluno1, enquanto para o outro aluno, aluno2. Para se mandar uma mensagem para um dos objetos utiliza-se a chamada “sintaxe do ponto” (dot syntax). Esta sintaxe indica que o acesso a um atributo ou método de um objeto deve ser feita utilizando a forma “objeto.método” ou “objeto.atributo”. No nosso exemplo, para chamar o método imprimirNome no objeto aluno1, deve ser utilizada a notação aluno1.imprimirNome(). Dessa forma, representa-se a ativação de uma mensagem neste objeto. 2.2. Agregação/Composição A ideia de agregação ou composição estabelece a criação de novas classes de objetos a partir da junção de classes já existentes. Essa ideia de composição é muito comum para se representar relações do tipo todo-parte, como no caso de uma turma ser composta por instâncias de outras classes, como um professor, um conjunto de alunos, dentre outros. Da mesma forma que a classificação/instanciação são processos inversos, para a composição de classes são definidas duas operações diferentes: 26
  • 27. Programação II » Operação de Agregação: Quando unimos um conjunto de objetos para formarmos um novo objeto; » Operação de Decomposição: Quando, analisando um objeto, isolamos cada um de seus componentes. Veja o seguinte exemplo: Figura 22 – Agregação/Decomposição Neste exemplo, a classe Automóvel pode ser decomposta nas classes Placa e Motor. Este processo, chamado de decomposição, realiza uma análise sobre a classe Automóvel e aplica um refinamento. Refinar significa deixar ainda mais claro a estrutura de um determinado conceito. O processo inverso faz uma síntese de conceitos já existentes para criar um novo conceito. Há uma notação especial em UML para representar agregação, como ilustrado e exemplificado na Figura 23. Um losango vazado é anexado à extremidade de um caminho de associação ao lado do agregado (o todo) para indicar agregação. Figura 23 – Notação UML para agregação; Tipos de Agregação Há uma distinção entre dois tipos de agregação: a agregação compartilhada e a composição. No primeiro tipo, representado pela ideia de uma disciplina que contem um 27
  • 28. Programação II professor e uma sala vinculada, objetos contidos podem existir sem serem parte do objeto que os contém. Em outras palavras, um professor continuará a existir, mesmo que não haja o conceito Disciplina. No caso da composição, objetos contidos não fazem sentido fora do contexto do objeto que os contém. No exemplo apresentado, um pedido contem itens e um Cliente vinculado. Se você destruir o pedido, os itens são destruídos junto, pois eles não tem sentido fora do pedido. Neste caso, o losango anexado à extremidade da classe agregadora deve ser preenchido, e não vazado. 2.3. Associações Simples As entidades envolvidas apresentam existências independentes, mas existe uma ligação entre elas. A agregação não é única forma de relacionamento entre objetos e classes. Classes e objetos podem formar associações, que consistem na descrição genérica de uma ou mais ligações entre as classes, permitindo que objetos de uma classe utilizem recursos de outros objetos. Ao se estabelecer associações entre classes, em geral se estabelece o significado de uma classe “usar” ou “possuir” outra. Para representar associações entre classes, UML utiliza uma linha unindo as duas classes. Alguns exemplos de associações são descritas abaixo. Figura 24 – Associações entre classes Nos exemplos acima, temos que um cliente está vinculado a um produto, e vice-versa. Uma conta possui um histórico de transações. Um hóspede está vinculado à um quarto. Associações podem ainda ser refinadas inserindo a multiplicidade nos relacionamentos entre classes. Por exemplo, um único cliente pode estar vinculado a zero ou mais (sem limites) pedidos. Um velocista pode participar de zero ou mais corridas, e uma corrida deve ter no mínimo dois e no máximo seis velocistas. 2.4. Encapsulamento Um dos aspectos mais positivos da programação modular foi a ideia de encapsulamento de informações. A programação orientada a objetos preserva este conceito. Encapsular dados em OO consiste em separar os aspectos externos de um objeto, os quais são acessíveis a outros objetos, dos detalhes internos de implementação do objeto, os quais permanecem escondidos dos outros objetos. O uso de encapsulamento evita que objetos possuam grandes dependências entre si, de modo que uma simples mudança em um objeto possa trazer grandes efeitos colaterais e problemas para outros objetos. Como vimos no capítulo I, o conceito de encapsulamento não é exclusivo da abordagem de orientação a objetos. Entretanto, a habilidade de se combinar estrutura de dados e comportamento em uma única entidade torna o encapsulamento mais elegante e mais poderoso do que em linguagens convencionais que separam estruturas de dados e comportamento. 28
  • 29. Programação II No paradigma OO, o encapsulamento institui conceitos e regras que ajudam a promover a modularidade entre objetos. Para isso, o acesso a componentes de um objeto é controlado e, especialmente, os atributos de um objeto só devem ser modificados pelos métodos do próprio objeto. Veja como isso ajuda a proteger um programa. Imagine a classe Conta que representa uma conta corrente, cujos atributos são seu número e seu saldo na Figura 25. Figura 25 – O benefício do encapsulamento De acordo com projeto, o saldo de uma conta não pode ser menor que zero. Mas da forma como até agora conhecemos classes, o acesso a atributos e métodos é liberado. Logo, qualquer objeto poderia ter o atributo saldo acessado diretamente, e modificado para um valor inválido, como representado no exemplo. Para sanar este problema, linguagens orientadas a objetos oferecem mecanismo que modificam a visibilidade (escopo) de atributos e métodos. É possível então estabelecer que todos os atributos de uma classe só possam ser acessados de métodos definidos dentro da própria classe. É dito então que o escopo deste método é privado à sua classe. No nosso exemplo, a modificação do saldo de uma conta só poderá ser feita através do método debitar(valor) que internamente estabelece regras que não permitem que o saldo da conta fique negativo. A ideia do encapsulamento faz também com que o sistema não dependa das implementações internas das classes, mas sim de suas interfaces. A interface de um objeto é representada pelo conjunto de todos os métodos que este objeto oferece a outros objetos. A interface de um objeto é que é externamente visível, e que protege dados internos, além de outras operações que não devem ser disponibilizadas ao mundo externo. Imagine uma classe que represente o conceito de uma coleção de pessoas, e que forneça métodos para manipular esta coleção, como inserir uma pessoa, consultar uma pessoa pelo nome, etc. Internamente, esta classe poderia utilizar diferentes estruturas para guardar a coleção de pessoas, como um vetor, uma lista dinâmica ou mesmo um banco de dados. Porém, para quem vai utilizar algum objeto desta classe, isso não importa. O que importa é que exista um método para inserir, outro para consultar, e assim por diante. Desta forma, alterações dentro da classe não afetarão o restante do sistema. Por exemplo, pode- se trocar a implementação interna da classe, mudando de um vetor para o banco de dados. Se a interface for mantida, os objetos que usam não sofreram nenhum impacto, o que torna a manutenção mais fácil. Por estes motivos, na orientação a objetos é muita utilizada a expressão “programar 29
  • 30. Programação II para a interface”. Esta expressão indica a ideia que a interface de um objeto representa um contrato entre uma classe de objetos. Enquanto o contrato for mantido, objetos que dependam dos métodos de uma classe não serão prejudicados. 2.5. Generalização/Especialização (Herança) Generalização e especialização são abstrações que permitem o reuso de objetos através da criação de classes de objetos a partir de outras classes. No caso, a especialização é o mecanismo pelo qual pode-se definir uma nova classe de objetos a partir de uma classe já existente. Esta nova classe poderá aproveitar o comportamento e possíveis atributos da classe estendida. A classe sendo refinada é chamada de superclasse ou classe base, enquanto que a versão refinada da classe é chamada uma subclasse ou classe derivada. A generalização é o inverso da especialização. A Figura 26 ilustra esta relação: Figura 26 – Generalização/Especialização, a base para a Herança entre classes Neste exemplo, a superclasse Estudante é refinada em dois tipos mais específicos, os de graduação e os de pós-graduação. Diz-se que cada classe derivada herda as características de sua classe base. Por conta disso é mais comum essa abstração serem tratadas em linguagens de programação orientadas a objetos como Herança. No nosso exemplo, a classe Estudante poderia ter como atributos: nome ou instituição vinculada, estes também são atributos de estudantes de graduação ou pós-graduação. Cada classe derivada não apenas herda as características de seu ancestral como também pode acrescentar seus atributos e operações específicos, como o curso para o Estudante de Graduação. Em UML, a notação para generalização é representada por uma associação entre superclasse e subclasses, onde um triângulo é posto na extremidade próxima à superclasse (Figura 27). 30
  • 31. Programação II Figura 27 – Representação UML para Herança; Exemplo para uma hierarquia de classes É importante salientar que a herança não vale apenas para dados, mas também para métodos. No mesmo exemplo, a classe Estudante define um método imprimeDados. Portanto, as subclasses da classe Estudante também herdam este comportamento. Com isto, embora o método não seja definido na classe EstudanteGraduação ou EstudantePos, qualquer objeto de uma destas duas classes pode ter o método imprimeDados sendo invocado. A correta chamada de métodos ou o acesso a atributos em classes que possuam uma relação de herança ocorre através da busca nas classes que participam da hierarquia. Exemplificando: quando um método é chamado em um objeto de uma classe, a especificação deste método é procurada na classe deste objeto. Se este método não é encontrado, busca-se então na definição de sua superclasse, e assim por diante, pois uma hierarquia de herança pode ser formada por várias classes, recursivamente aplicada a um número arbitrário de níveis. A Figura 28 exemplifica uma relação de herança em mais de um nível. Figura 28 – Múltiplos níveis de herança 31
  • 32. Programação II Neste exemplo, o Estudante de Graduação além do curso, possui também como atributos herdados a matricula (da classe Estudante) e o nome (da classe Pessoa). Uma subclasse pode também sobrepor uma característica de sua superclasse, o que significa que a nova característica local à subclasse irá substituir a característica de sua superclasse. Neste caso, esta ação é chamada de sobreposição. Ainda no exemplo anterior, a classe Estudante sobrepõe o método imprimeDados da classe Pessoa. Em outras palavras, a execução deste método em objetos da classe Estudante obedecerá a esta nova definição. Note que esta alteração também afeta objetos das classes EstudanteGraduação e EstudantePos. Objetos dos tipos Pessoa e Empregado executam a definição original do método. A definição e uso de herança traz consigo também um princípio muito importante para a orientação a objetos que é o princípio da substituição. Este princípio se baseia no fato que, se uma subclasse herda métodos e atributos de sua superclasse, em qualquer lugar de um programa que você possa utilizar uma instância de superclasse, você também deve poder utilizar uma instância de qualquer subclasse desta classe. Embora pareça complicado, imagine um programa que faz uma chamada ao método imprimeDados de um objeto Pessoa, de acordo com a hierarquia de classes da Figura 27. Pelo princípio da substituição, você pode substituir este objeto Pessoa por qualquer outro objeto que seja instância de alguma subclasse de Pessoa, como Estudante, Empregado, EstudantePos ou EstudanteGradução. Como todos eles vão possuir o método imprimeDados, o programa vai continuar a funcionar sem problemas. Este princípio é muito útil para facilitar a extensão de programas. Herança Simples e Herança Múltipla A herança pode ser de dois tipos: Simples e Múltipla. A herança simples é quando uma classe é subclasse de somente uma superclasse, enquanto a herança múltipla ocorre quando uma classe é subclasse de várias superclasses e, consequentemente, herda as características de cada uma delas. Os exemplos que vimos até agora foram todos de herança simples. A Figura 29 apresenta um exemplo de uma herança múltipla. Figura 29 – Exemplo de Herança Múltipla Neste caso, note que a classe VeiculoAnfibio possui duas superclasses, Carro e Barco. Desta forma, ela herda métodos e atributos destas duas classes. Herança múltipla não se limita a apenas duas classes, de acordo com o contexto do mundo que se queira modelar. Porém, a herança múltipla traz um problema: o conflito de atributos ou métodos herdados das superclasses. Em nosso exemplo, note que tanto Carro quanto Barco possuem um método parar. Imagine então o que aconteceria se fosse feita uma chamada ao método parar em um objeto do tipo VeiculoAnfibio. Qual implementação de parar deveria ser chamada? 32
  • 33. Programação II Por conta dessa e de outras questões, a Herança Múltipla não é implementada em todas linguagens de programação, como no caso de Java. Porém, pode ser encontrada em outras linguagens como C++ e SmallTalk. 2.6. Polimorfismo O termo polimorfismo é originário do grego, e etimologicamente quer dizer “muitas formas”. Na orientação a objetos, isso significa que um mesmo tipo de objeto, sob certas condições, pode realizar ações diferentes ao receber uma mesma mensagem. Ou seja, objetos podem ter reações diferentes ao mesmo estímulo (Figura 30). Figura 30 – Polimorfismo: Objetos têm diferentes reações a um mesmo estímulo Polimorfismo permite o envio de uma mesma mensagem a objetos distintos, onde cada objeto responde da maneira mais apropriada para a classe chamadora. No exemplo da Figura 30, a mesma mensagem “desenhar” pode ser enviada a três objetos distintos: o quadrado, o círculo e o triângulo. Os três sabem como tratar esta mensagem, porém cada um realizará ações diferentes. Existem dois tipos principais de polimorfismo: a sobrecarga e a sobreposição. Na sobrecarga, uma mesma classe de objetos possui métodos com o mesmo nome, porém quantidade ou tipo de parâmetros diferentes. No momento da chamada do método, dependendo do parâmetro, um método ou outro será chamado. Por exemplo, a classe Pessoa (Figura 31) possui dois métodos imprimir. O primeiro recebe apenas um parâmetro, enquanto o segundo recebe dois. Figura 31 – Sobrecarga de métodos Já a sobreposição ocorre somente associada à herança. Quando um método definido na superclasse não serve da forma original para a subclasse, ele tem de ser redefinido. Como na redefinição a assinatura deve ser mantida, o novo método sobrepõe o método definido na superclasse. Veja como exemplo a Figura 32. Existem dois tipos de Funcionário: o que recebe um salário fixo (Empregado) e outro cujo salário é calculado de acordo com suas vendas 33
  • 34. Programação II (EmpregadoComissão). O segundo tipo tem as mesmas características do primeiro, portanto convém que se utilize herança para reaproveitar seus dados. Porém, o calculo de seu salário é totalmente diferente. Neste caso, a subclasse modifica (sobrepõe) o comportamento do método que calcula o salário para a classe EmpregadoComissão. Figura 32 – Sobreposição de métodos Neste caso, quando um objeto for do tipo Empregado, o calculo do salário obedecerá a regra definida na superclasse. Mas quando o objeto for do tipo EmpregadoComissão, a regra utilizada é aquela que foi redefinida nesta classe. Em resumo: » O método a ser chamado é aquele pertencente ao objeto o qual a chamada está relacionada; » Caso o objeto não possua este método, a chamada é transferida para a superclasse, e assim por diante até que o método seja encontrado; Porém, ao contrário da sobreposição, métodos sobrepostos na subclasse precisam ter a mesma assinatura de seus equivalentes na superclasse. Em outras palavras, precisam ter o mesmo nome; o mesmo número de parâmetros e o mesmo tipo de parâmetros de entrada e saída. Exercícios 1. No contexto da programação orientada a objetos, o que é um objeto? 2. No contexto da programação orientada a objetos, o que é uma classe? Diga também o que são métodos e variáveis de instância. 3. Indique qual é o principal benefício obtido quando os atributos de uma classe não são visíveis a outras classes? Qual é o nome desta técnica de programação? 4. Explique o que é o relacionamento de herança entre classes. 5. Para você, qual o benefício do polimorfismo no paradigma orientado a objetos? 6. Utilizando orientação a objetos, indique quais seriam as classes, seus atributos, métodos e associações para os seguintes sistemas: a) Uma universidade; b) Um acervo de mídias (CDs e DVDs) c) Um filme. 34
  • 35. Programação II Vamos Revisar? Neste capítulo, você foi apresentado a uma nova forma de organizar os conceitos para criação de programas de computador. A orientação a objetos baseia-se em uma aproximação da forma como os seres humanos organizam e realizam ações no mundo real. Para isso, novas abstrações como classificação, agregação, associação, dentre outras são fundamentais para que os programas sejam organizados de forma a permitir um maior reuso de código e maior flexibilidade de manutenção. Conceitos como classes, objetos, métodos e atributos são fundamentais em linguagens orientadas a objetos, vão fazer parte do dia a dia deste curso. A partir deles, conceitos mais avançados como herança e polimorfismo são gerados, e serão mais detalhados adiante nesta disciplina. Por enquanto, é importante que os conceitos deste capítulo seja amadurecidos em sua cabeça. 35
  • 36. Programação II Capítulo 3 O que vamos estudar neste capítulo? Neste capítulo, vamos estudar os seguintes temas: » Linguagem de Programação Java » Java Software Development Kit – JSDK » O ambiente de programação JCreator Metas Após o estudo deste capítulo, esperamos que você consiga: » Identificar as principais características da Linguagem Java; » Instalar e configurar o Kit de desenvolvimento necessário para compilar e executar seus programas em Java; » Instalar o ambiente de programação JCreator; 36
  • 37. Programação II Capítulo 3 – A Linguagem Java Vamos conversar sobre o assunto? Nos capítulos iniciais deste volume você aprendeu sobre a necessidade de melhorar a forma como organizamos os conceitos em linguagens de programação e como a orientação a objetos busca melhorar o reuso e a manutenção de programas. Bem, até agora, tudo foi bastante teórico. Então chegou a hora de começarmos a ver como na prática isso tudo funciona. Para isto, este capítulo introduz a linguagem de programação orientada a objetos mais popular no mundo: Java. 1. Introdução Você Sabia? A linguagem de programação Java tem origem no início da década de 90, dentro da Sun Microsystems. Na época, uma equipe liderada por Patrick Naughton, Mike Sheridan, e James Gosling tinha como objetivo projetar uma nova linguagem de programação capaz de criar softwares capazes de comunicar diferentes dispositivos entre si. Originalmente, batizou-se esta linguagem de Oak (carvalho, em inglês), em homenagem a um espécie de árvore que os integrantes do projeto avistavam de sua sala. Inicialmente a proposta de interoperabilidade de programas não foi muito bem aceita pelo mercado, o que então fez com os objetivos fossem modificados. Na época, o Você sabia que a linguagem Java tem uso da Internet estava crescendo vertiginosamente. Foi então que a Sun viu nesta expansão esse nome devido a uma oportunidade de usar Oak. A linguagem passaria então a ser voltada para construir um café? aplicações para Web. A linguagem foi rebatizada e passou a se chamar Java, sendo Durante o projeto os apresentada oficialmente em 1995. participantes tomava muito café, e gostavam Desde então, Java foi rapidamente adotada pelo mundo, mais rapidamente que principalmente de qualquer outra linguagem de programação até então. Grandes fornecedores de tecnologia um proveniente da como IBM, Oracle, Netscape, dentre outros, passaram a apoiar Java. ilha de Java. No meio do projeto Green, A linguagem evoluiu muito ao longo dos anos. Hoje, mas que uma linguagem, os projetistas foram avisados que já havia Java pode ser vista como uma plataforma de desenvolvimento e execução de programas uma linguagem com em diversas plataformas. Você encontra programas Java na Web, dos telefones celulares, o nome de oak, que mainframes, cartões inteligentes, dentre outros. Com isso, a linguagem é dividida em 3 inicialmente era o grandes segmentos: escolhido. Com isso, os projetistas resolveram 1. JEE (Java Enterprise Edition): indicado para aplicações coorporativas, com homenagear a ilha que produzia o café tão necessidade gerenciamento de transações, balanceamento de carga, concorrência, apreciado por todos. dentre outros; 2. JSE (Java Standar Editon): é o ambiente de desenvolvimento mais utilizado. Isso porque seu uso é voltado a PCs e servidores, onde há bem mais necessidade de aplicações; 3. JME (Java Micro Edition): é o ambiente de desenvolvimento para dispositivos móveis ou portáteis, como telefones celulares e palmtops. Hoje, estima-se que haja uma comunidade de mais de quatro milhões de 37
  • 38. Programação II programadores Java no mundo. Existem também grupos de usuários Java, chamados JUGs (Java User Groups), que são utilizados para troca de ideias, dúvidas e melhores práticas no uso da tecnologia Java. No Brasil, existem vários, como o DF-JUG (de Brasília) ou CE- JUG(do Ceará). Existem diversos livros publicados sobre a linguagem, além de diversos ambientes de programação e desenvolvimento. 2. Características da Linguagem Durante seu projeto, a linguagem Java teve uma série de requisitos que podem se apontados como fatores de seu sucesso. 1. Java é orientada a objetos: Java foi baseada no modelo de outras linguagens de programação OO, no caso, Simula67 e SmallTalk. Com isso, os conceitos de herança, polimorfismo e encapsulamento são implementados pela linguagem. A sintaxe e seu sistema de tipos é bem parecido com C e C++, o que facilitou a migração de programação de programadores já acostumados com estas linguagens; 2. Java é portável: Este conceito indica que um mesmo programa escrito em Java pode ser executado em diferentes plataformas hardware ou sistema, sem grandes ou nenhuma mudanças. Por conta desta característica, é comum se associar a Java o seguinte jargão: “escreva uma vez, execute em qualquer lugar; 3. Java é segura, confiável e robusta: Ao contrário de suas predecessoras, Java não trabalha com ponteiros. Em outras palavras, um programador Java não tem acesso direto a posições de memória, um dos grandes problemas para quem trabalha com linguagens como C ou C++. Java possui um mecanismo de tratamento de exceções em que os erros que possam vir a ocorrer durante operações efetuadas são tratadas paralelamente em outro trecho de código do sistema. Um erro que durante a execução do programa poderá ser capturado sem imprevistos como, por exemplo, acessos inválidos de memória do sistema operacional, ou do gerenciador de arquivos, que podem acarretar problemas como o travamento, desligamento do computador e perda de arquivos significativos; 4. Java promove reuso e facilita a manutenabilidade: Java possibilita a criação de componentes reutilizáveis, ou seja, uma vez criadas funcionalidades para os mesmos, estes poderão ser reutilizáveis posteriormente. Com isso é proporcionado um baixo custo de produção e manutenção de códigos gerados com os demais sistemas que venham a ser desenvolvidos; 5. Java é distribuída: Java possui a capacidade de compartilhamento de informações possibilitando a distribuição de tal forma que haja processamento em máquinas distintas. Possui integração com o protocolo TCP/IP que facilita a programação para acessos remotos, utilizando protocolos como: HTTP e FTP; 6. Java permite a carga dinâmica de aplicações: Java oferece o recurso de que aplicações chamadas applets possam ser carregadas remotamente e executadas no contexto de um browser, ao ler uma página na Web. Ao fazer isso, Java introduziu a interatividade na Web, permitindo que aplicações pudessem ser descarregadas e utilizadas automaticamente por usuários, sem necessidade de instalação, ou atualizações de versões. Ao mesmo tempo, applets possuem um criterioso modelo de segurança que previne o acesso de aplicações remotas a possíveis ações danosas no computador do usuário que rode um applet; 7. Java é livre e gratuita: Você não paga nada para criar um programa em Java. O software para execução e construção de programas é disponibilizado gratuitamente 38
  • 39. Programação II na Internet. Além disso, existem vários ambientes gratuitos para facilitar a construção e depuração de programas Java. 3. Máquina Virtual Java: o alcance de portabilidade Uma das características mais importantes da linguagem Java é a portabilidade. Para isto, Java promove o conceito que nada na linguagem deve ser específico de uma plataforma específica. O que na realidade Java faz, é criar a ideia de um computador abstrato sobre o qual o programa deve ser executado. Esse computador abstrato é chamado de máquina virtual Java (JVM). Na realidade, a máquina virtual Java é uma especificação fornecida a início pela Sun, e seu funcionamento une a ideia de compilação e interpretação de programas. Vamos ver como isso funciona. Para criar um programa Java precisamos criar sua especificação através da sintaxe da linguagem. Como em praticamente toda linguagem de programação isso é feito através da edição de um arquivo texto. A partir de um programa escrito corretamente, a etapa que segue é a compilação do programa para geração de sua versão executável. Aqui vem uma grande diferença. Em vez de gerar um arquivo executável que é voltado para um computador ou sistema operacional específico, Java gera uma versão intermediária do programa, o bytecode. O bytecode é um arquivo neutro e independente de plataforma. Ele representa o programa executável e livre de erros, como uma linguagem de máquina destinada a um processador virtual especificado pela máquina virtual Java. Desta forma, qualquer implementação de uma máquina virtual Java deve ser capaz de executar este programa. O que de fato acontece, pois hoje existem implementações da máquina virtual Java para as mais diversas plataformas, como Windows, Linux, MacOS, dentre outros (Figura 33). Figura 33 – O processo de compilação e execução de um programa Java A JVM utiliza o mecanismo de interpretação para executar os bytecodes que correspondem ao programa originalmente escrito pelo programador. O uso de uma máquina virtual acarreta em um tempo a mais na execução do programa, o que indica que programas escritos em Java tendem a ser mais lentos que programas equivalentes escritos em C ou C++. Porém, a facilidade na migração de um sistema entre diferentes plataformas é um requisito cada vez mais importante na construção das aplicações modernas. Ou seja, é um benefício que se paga. Além disso, as atuais implementações de JVM fazem uma série de otimizações que diminuem a diferença em relação à execução de um programa Java e programas compilados diretamente para uma plataforma específica. 39
  • 40. Programação II 4. Codificando um primeiro programa Java Uma forma muito utilizada para promover a familiarização com uma nova linguagem é a criação de um programa simples que apresenta uma mensagem na tela. Vamos aqui também utilizar esta estratégia. Para isso, vamos utilizar um editor de textos plano (o bloco de notas, por exemplo) para editar nosso programa. Um programa em Java é um arquivo texto, que por padrão, possui a extensão .java. A Figura 34 apresenta o programa AloMundo.java, que será utilizado para nosso primeiro contato com a linguagem. Figura 34 – Programa AloMundo.java Digite este programa e grave o arquivo em um diretório de seu computador. No meu caso, eu criei um diretório c:Java e utilizarei o mesmo em meus exemplos. Vamos então analisar este programa. Importante: Java faz diferenciação entre letras minúsculas e maiúsculas. Portanto, ao digitar o programa AloMundo, faça-o mantendo o mesmo padrão em relação ao texto apresentado neste capítulo, inclusive para o nome do arquivo AloMundo.java. A primeira linha marca o início da declaração de uma classe em Java. Em Java, tudo é uma classe. Como visto no capítulo anterior, classes são utilizadas para criar objetos. Então, a definição de uma classe em Java utiliza a palavra reservada class. Associada à definição da classe, temos outra palavra reservada: public. Esta palavra reservada é um qualificador, que no caso indica a visibilidade da classe, e que será detalhada mais adiante no curso. Por enquanto, guarde apenas na cabeça que a definição de uma classe segue este padrão: public class <NOME_DA_CLASSE>. Seguido a definição da classe, vem a definição do corpo da classe. Java segue um padrão em que existem blocos que agrupam trechos de código e limitam o escopo de variáveis. Todo bloco em Java é limitado por chaves (“{“ e”}”). No nosso exemplo, as chaves que limitam o bloco da classe estão nas linhas 1 e 7. O corpo da classe AloMundo é extremamente simples. Existe apenas um método: public static void main(String args[]){ System.out.println(“Alô mundo!!!”); } Este método representa o ponto de entrada da classe. De forma análoga com C, este método é aquele que é executado quando pedimos para o interpretador Java executar 40
  • 41. Programação II a classe. A partir deste ponto, outros métodos podem ser chamados, objetos podem ser criados, etc. Vamos analisar um pouco mais a fundo a assinatura deste método. Assim como para a classe, deve-se declarar a visibilidade do método. Neste caso, a public ideia que qualquer classe pode executar este método. É um outro qualificador, que indica que o método deve ser compartilhado por todos os objetos que são criados a partir desta classe. Os métodos static podem ser invocados, mesmo quando não foi criado nenhum objeto para a classe. Detalhes static sobre métodos estáticos serão vistos posteriormente no curso. Por hora, você precisa saber que particularmente o método main precisa ter essa qualificação porque ele é chamado sem que se crie nenhum objeto de sua classe (a classe AloMundo). É o valor de retorno da função, quando a função não retorna nenhum valor ela void retorna void. Vamos ver no curso que métodos, assim como funções podem retornar valores como números, palavras, vetores e, é claro, objetos. Toda classe em Java deve conter métodos. Porém, existe um método que torna uma classe um programa executável. Este método é chamado de método principal main (main). Este é um nome particular de método que indica para o compilador o início do programa. É o argumento de main e por consequência do programa todo, ele é um vetor (String (array) de Strings que é formado quando são passados ou não argumentos através args[]) da invocação do nome do programa na linha de comando do sistema operacional. Então, resumindo: Toda classe que quiser executar ações deve fornecer um método com a assinatura: public static void main(String args[]) A partir daí, como em todo programa, seguem-se as instruções. No nosso caso, temos uma única instrução: System.out.println(“Alo Mundo!”); Esta instrução representa a maneia mais simples de imprimir mensagens na tela de seu computador. Como dito anteriormente, tudo em Java é representado através de classes e objetos. Esta instrução acima também segue este padrão. System é o nome de uma classe fornecida pela linguagem Java e que representa o sistema onde o programa está sendo executado. Esta classe possui uma série de atributos e métodos. Um destes atributos é out. Este atributo representa a saída padrão do sistema, no caso, a tela. Na realidade, out é um objeto de outra classe (PrintStream), que permite escrever mensagens através de seus métodos. Dentre os vários métodos fornecidos, existe o println, que imprime a String passada como parâmentro e e posiciona o cursor na linha abaixo. Analogamente, existe também o método print que não avança linha. Por hora você pode guardar esta linha de código como o comando para imprimir mensagens na tela, onde o argumento que vem entre aspas é a String a ser impressa. O ; “ponto e vírgula” separa os comandos, sendo portanto obrigatório para encerrar cada instrução. Visto isso, vamos ver como este programa deve ser executado. 41
  • 42. Programação II 5. JSDK – Java Software Development Kit Bem, visto a definição de um programa simples em Java, vamos aos próximos passos, que seriam sua compilação e posterior execução. Para, precisamos então ter acesso às ferramentas que permitam a realização destes passos. Formalmente, a linguagem tem padronizada a sua especificação, mas não a implementação das ferramentas necessárias à execução de seus programas. No entanto, a Sun fornece uma implementação de referência, assim como uma série de programas utilitários para a plataforma Java. Este conjunto é chamado de JDSK (Java Software Development Kit) é está disponível gratuitamente no site da Sun (http://java.sun.com). O JSDK ou simplesmente JDK possui versões para diferentes plataformas, como Windows ou Linux. Logo, a primeira coisa que você precisar fazer é baixar a versão correta para a sua plataforma (no caso, sistema operacional). Neste texto, eu utilizo a versão do JDK para Windows 7. Após instalar, é criada uma estrutura de diretórios semelhante à descrita na Figura 35, onde o nome do diretório jdk1.X varia de acordo com a versão a ser instalada. Nesta estrutura destaca-se o diretório bin, que guarda a principais ferramentas necessárias para execução e compilação dos programas. Portanto, é extremante recomendável que você inclua este diretório no caminho de busca da execução de programas em seu sistema operacional. Para isto, basta atualizar a variável PATH, fazendo ela também apontar para este diretório. Figura 35 – Estrutura de diretórios do JSDK Todas as ferramentas fornecidas no JSDK através de linhas de comando. Ou seja, para executá-las, basta abrir um prompt de comando e chamar a ferramenta. Dentre as ferramentas fornecidas, existem aquelas que são indispensáveis à execução dos programas, e outras que tem um grau de importância menor. Dentre estas destacam-se o compilador javac e o interpretador java. O compilador javac é o responsável pela geração dos bytecodes a partir de um programa fonte em java. Para ser utilizado, a forma mais simples é utilizando a sintaxe: javac <opções> NOME_CLASSE Para o nosso exemplo, dentro do diretório onde se encontra a classe, basta digitar este comando, que será gerada uma versão bytecode do programa AloMundo.java. Os arquivos bytecode tem o mesmo nome da classe, porém com a extensão .class. A Figura 36 mostra o processo de compilação e o arquivo gerado para o programa AloMundo. 42
  • 43. Programação II Figura 36 – Compilação de um programa Java É importante dizer que se uma classe faz referência a outra classe, as duas são compiladas. Se no mesmo diretório houver mais classes e quisermos compilar todas, é possível utilizarmos mascaras. Por exemplo, para compilar todas a classes, utilizaríamos a sintaxe: javac *.java É possível também por uma questão de organização, separar os arquivos bytecode dos arquivos fonte. Para isto, pode-se utilizar a opção –d pode ser utilizado para especificar uma localização diferente para armazenar o arquivo .class gerado após a compilação: javac AloMundo.java –d c:Javabytecode Uma vez gerado o bytecode, segue-se a execução do programa. Para isto deve-se utilizar o interpretador java. Quando o bytecode é utilizado pelo interpretador, a extensão .class é desconsiderada. Por este motivo, não é necessário especificá-la na linha de comando. Sendo assim, , para executar o programa, utiliza-se a sintaxe: javac <opções> NOME_CLASSE A execução do nosso programa é apresentado na Figura 37. Figura 37 – Execução de um programa Java Além destas ferramentas, o JSDK ainda fornece outros programas utilitários, que embora não sejam essenciais como o compilador e o interpretador, oferecem recursos importantes para o bom uso de Java. Por exemplo, a ferramenta javadoc representa um avanço no que diz respeito a documentação de seus programas. Através de comentários em um formato padronizado escrito no próprio código, a ferramenta javadoc gera automaticamente um conjunto de páginas HTML, onde as informações sobre classes, métodos e atributos são organizadas através de ligações dinâmicas, no formato já familiar aos sites da Internet. Vamos ver este 43
  • 44. Programação II formato de documentação nos próximos capítulos de nosso curso. A ferramenta jar é utilizada para empacotar arquivos Java. Em geral, arquivos .jar empacotam arquivos .class somente. O empacotamento de arquivos .class pode ser útil quando se deseja disponibilizar um programa para execução, mas o código não precisa ser fornecido uma vez que nenhuma alteração será realizada no mesmo. De outra forma, um .jar pode conter também arquivos .java. Alguns comandos possíveis com o comando jar são: Para criar um arquivo .jar jar cf arquivo.jar *.class Para listar o conteúdo de um arquivo .jar jar tf arquivo.jar Para extrair o conteúdo de um arquivo .jar jar xf arquivo.jar Outra utilização de empacotamento jar é quando se deseja disponibilizar um conjunto de classes para reutilização por outras aplicações. Estes outras aplicações não irão manipular diretamente esses classes empacotadas e nem vão “executar” essas classes, mas sim, utilizá-las para o desenvolvimento de alguma aplicação. Neste caso, essas classes empacotadas servem como bibliotecas que podem ser utilizadas por outras aplicações. Como dito no início deste capítulo, um applet é um tipo de programa Java utilizado em browsers web. Esses programas ficam armazenados em servidores web e quando da execução, são carregados pela rede para serem executados nos browsers web. Java fornece uma ferramenta para testar esse tipo de programa, sem a necessidade de utilização de um servidor ou browser web. Para tal, basta utilizar o comando appletviewer. appletviewer pagina.html Onde, appletviewer é a ferramenta de visualização de Applets e pagina.html, corresponde ao arquivo HTML no qual o applet será carregado para execução. 6. JCreator: Ambiente de programação de iniciantes Como você percebeu, para compilar e executar programas basta um editor de textos e kit de desenvolvimento fornecido gratuitamente pela Sun. Porém, na prática, o desenvolvimento de programas se dá por meio de ferramentas que facilitem ainda mais este processo, os chamados ambientes integrados de desenvolvimento – IDE (do inglês, Integrated Development Environment). Estes ambientes criam uma interface para o programador, permitindo, entre outras coisas: a compilação e execução de programas através de interfaces gráficas, ferramentas de depuração, dentre outras. Existem vários ambientes de programação disponíveis para Java. Alguns são gratuitos, outros não. Aqui segue uma pequena lista destas ferramentas: » Eclipse: IDE gratuita fornecida pelo projeto Eclipse, de código aberto, que fornece uma série de extensões para facilitar a construção de programas de computador. URL: http://www.eclipse.org/ » Netbeans: IDE gratuita fornecida pela Sun microsystems. O NetBeans IDE é um ambiente de desenvolvimento integrado gratuito e de código aberto para desenvolvedores de software. URL: http://netbeans.org/ » Jbuilder: IDE paga para desenvolvimento de aplicações na tecnologia Java criada pela Borland. URL: http://www.borland.com/br/products/jbuilder/ 44
  • 45. Programação II » BlueJ: IDE gratuita para desenvolvimento Java, desenvolvida principalmente para iniciação na programação orientada a objeto. URL: http://www.bluej.org/ Destas ferramentas, destacam-se as 3 primeiras, principalmente para o desenvolvimento profissional. Porém, devido a gama de funcionalidades que estas apresentam, para um programador iniciante, elas podem mais confundir que ajudar. Portanto, vamos utilizar nesta disciplina um ambiente de programação mais simples chamado JCreator. JCreator é um IDE bem leve, que possui uma versão específica e gratuita para o aprendizado de Java. Esta versão gratuita, LE(Learn Edition), for criado pela Xinox Software e possibilita também o desenvolvimento em outras linguagens, como JavaScript,XML,HTML. O site de download da ferramenta é o http://www.jcreator.com. O tamanho de seu instalador gira em torno de 4Mb, e o processo de instalação é bem simples. Seu único requisito é que antes de sua instalação, o JSDK já deve estar instalado. A Figura 38 abaixo mostra um screenshot da tela inicial do JCreator. Figura 38 – Tela Inicial do JCreator O JCreator trabalha com a ideia de espaços de trabalho (workspaces) e projetos. Um projeto possui um conjunto de classes que juntas constituem uma aplicação. Em geral, uma aplicação Java é composta por centenas de arquivos. Um workspace é uma pasta no seu computador onde ficam armazenadas as informações sobre um projeto. Para criar um projeto, utiliza-se o menu File > New > Project. O JCreator abrirá um assistente (Figura 39) para que você possa escolher o tipo de projeto que você quer. Escolha a opção Basic Java Application (Aplicação Básica Java) e pressione Next. 45
  • 46. Programação II Figura 39 – Jcreator Wizard: Criando um novo projeto Escolha um nome para seu projeto e pressione Finish (Figura 40). Figura 40 – Jcreator Wizard: Nomeando o projeto Confirme novamente a criação de projeto. Você deverá ter em sua tela agora parecido com o apresentado na Figura 41. Figura 41 – JCreator: Projeto Criado 46
  • 47. Programação II Como você pode notar, o projeto é criado e uma classe com o mesmo nome do projeto lhe é fornecida. Ela já vem com o esquema de uma classe que faz o mesmo que o nosso exemplo AloMundo.java, contendo trechos de comentários que ainda serão vistos no curso. Você pode obtar por trabalhar em cima desta classe ou criar uma nova classe. Para isso, utilize novamente o menu File, na sequência File > New > Class. Aparece um novo wizard para você. Digite o nome da classe AloMundo e pressione Finish. É apresentada para você uma classe, de forma semelhante com a Figura 42. Figura 42 – Classe AloMundo criada no JCreator Modifique a classe AloMundo fornecida pelo JCreator, deixando-o igual ao nosso exemplo do início deste capitulo. Vamos agora compilar e executar nossa classe. A compilação de uma classe é obtida através da opção do menu Build. Você pode optar por compilar uma única classe (Build) ou ou todas as classes do projeto (Build Project). Há também botões de atalho para as duas opções . Após compilar a classe, você deve obter uma resposta na janela abaixo, chamada Build Output. No nosso caso, você deve obter uma mensagem semelhante à descrita na Figura 43. Figura 43 – Resultado de um compilação sem erros no JCreator Por fim, a execução da classe. Para isso, você utiliza o menu Run. Nele você pode optar por executar o projeto ou a classe ativa. Todo projeto tem uma classe principal, que seria a responsável por iniciar da aplicação. Isso pode ser configurado nas propriedades do projeto. Vamos executar a classe AloMundo através da opção Run File. Para isso, certifique- se que a classe AloMundo é que está sendo apresentada no JCreator. A execução vai disparar uma nova compilação, e depois, na janela General Output, será apresentado o resultado da execução do programa. Você também pode utilizar o botão de atalho para Executar a classe ( ) . Você então deverá ver algo como na Figura 44. 47
  • 48. Programação II Figura 44 – Resultado da Execução da classe AloMundo no JCreator Como você percebe, um ambiente como o JCreator é uma mão na roda para evitarmos ter que trabalhar com as linhas de comando oferecidas pelo JSDK. O JCreator ainda lhe fornece uma janela File View, onde são apresentados os arquivos de seu projeto e uma janela Properties View, que mostra propriedades de diferentes itens de seu projeto, como do próprio projeto. Exercícios 1. Baixe e instale o Kit de Desenvolvimento Java adequado para seu computador; 2. Crie o programa AloMundo descrito neste capítulo. Compile-o e execute-o utilizando os programas apresentados no capítulo; 3. Edite o programa AloMundo e modifique o nome da classe para Alomundo. Para isso, mude a linha “public class AloMundo{“ para “public class Alomundo{“. Compile novamente. Qual o resultado da compilação? 4. Baixe e instale o JCreator; 5. Crie um projeto novo, com uma classe. Faça com esta classe imprima na tela seu nome; 6. Compile e execute esta classe no JCreator. Minibiografia James Gosling (Calgary, 19 de Maio de 1955) é conhecido como o pai da linguagem de programação Java. Ele fez o projeto original do Java e implementou o seu primeiro compilador e sua máquina virtual. Por este feito ele foi eleito para a United States National Academy of Engineering. Gosling está desde 1984 na Sun Microsystems. Gosling trabalha desde 2006 como CTO da Sun do grupo de desenvolvimento do produto. 48
  • 49. Programação II Vamos Revisar? Neste último capítulo, você foi apresentado(a) à linguagem de programação mais popular do mundo atualmente. O propósito deste capítulo foi principalmente apresentar as características que fizeram de Java, uma linguagem tão bem aceita por programadores no mundo todo. Posso afirmar com certeza que um destes motivos foi sua aderência ao paradigma orientado a objetos. Além disso, destaca-se sua proposta de portabilidade através de seu conceito de máquina virtual. Você também viu como é a estrutura de um programa simples em Java, que também serviu de exemplo para uso do compilador e interpretador inclusos no Kit de Desenvolvimento da linguagem. Por fim, você também conheceu o JCreator, uma ambiente de programação leve e simples, porém muito útil para programadores iniciantes na linguagem, e que será utilizado durante o curso para realização dos exercícios durante a disciplina. 49
  • 50. Programação II Conheça o Autor Fernando Trinta Sou professor de ciência de computação, formado pela Universidade Federal do Maranhão. Tenho Mestrado e Doutorado em Ciência da Computação pelo Centro de Informática da Universidade Federal de Pernambuco, com ênfase na área de Sistemas Distribuídos. Durante minha pós-graduação, estive envolvido com os temas de objetos distribuídos e educação a distância no Mestrado, e jogos digitais, middleware e computação ubíqua no Doutorado. Trabalhei no desenvolvimento de sistemas em várias empresas, privadas e públicas. Atualmente faço parte do corpo discente do Mestrado em Informática Aplicada da Universidade de Fortaleza (UNIFOR), no Ceará. Além da informática, gosto muito de esportes em geral e cinema. Mas nos últimos anos, duas novas paixões tomaram conta do meu mundo: Ian e Ananda. 50