50
Recife, 2010 Programação II UNIVERSIDADE FEDERAL RURAL DE PERNAMBUCO (UFRPE) COORDENAÇÃO GERAL DE EDUCAÇÃO A DISTÂNCIA (EAD/UFRPE) Fernando Antonio Mota Trinta Volume 1

Programacao ii volume1_v_final

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Programacao ii volume1_v_final

Recife, 2010

Programação II

UNIVERSIDADE FEDERAL RURAL DE PERNAMBUCO (UFRPE)

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

Fernando Antonio Mota Trinta

Volume 1

Page 2: Programacao ii volume1_v_final

Universidade Federal Rural de Pernambuco

Reitor: Prof. Valmar Corrêa de AndradeVice-Reitor: Prof. Reginaldo BarrosPró-Reitor de Administração: Prof. Francisco Fernando Ramos CarvalhoPró-Reitor de Extensão: Prof. Paulo Donizeti SiepierskiPró-Reitor de Pesquisa e Pós-Graduação: Prof. Fernando José FreirePró-Reitor de Planejamento: Prof. Rinaldo Luiz Caraciolo FerreiraPró-Reitora de Ensino de Graduação: Profª. Maria José de SenaCoordenação Geral de Ensino a Distância: Profª Marizete Silva Santos

Produção Gráfica e EditorialCapa e Editoração: Allyson Vila Nova, Rafael Lira, Italo Amorim e Gláucia FagundesRevisão Ortográfica: Marcelo MeloIlustrações: Allyson Vila NovaCoordenação de Produção: Marizete Silva Santos

Page 3: Programacao ii volume1_v_final

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

Page 4: Programacao ii volume1_v_final

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

Page 5: Programacao ii volume1_v_final

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.

Page 6: Programacao ii volume1_v_final

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.

Page 7: Programacao ii volume1_v_final

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

Page 8: Programacao ii volume1_v_final

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.

Page 9: Programacao ii volume1_v_final

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.

Page 10: Programacao ii volume1_v_final

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

Page 11: Programacao ii volume1_v_final

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

Page 12: Programacao ii volume1_v_final

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.

Page 13: Programacao ii volume1_v_final

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.

Page 14: Programacao ii volume1_v_final

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.

Page 15: Programacao ii volume1_v_final

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.

Page 16: Programacao ii volume1_v_final

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

Page 17: Programacao ii volume1_v_final

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

Page 18: Programacao ii volume1_v_final

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,

Page 19: Programacao ii volume1_v_final

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

Page 20: Programacao ii volume1_v_final

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.

Page 21: Programacao ii volume1_v_final

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.

Page 22: Programacao ii volume1_v_final

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.

Page 23: Programacao ii volume1_v_final

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;

Page 24: Programacao ii volume1_v_final

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.

Page 25: Programacao ii volume1_v_final

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.

Page 26: Programacao ii volume1_v_final

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:

Page 27: Programacao ii volume1_v_final

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

Page 28: Programacao ii volume1_v_final

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.

Page 29: Programacao ii volume1_v_final

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

Page 30: Programacao ii volume1_v_final

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).

Page 31: Programacao ii volume1_v_final

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

Page 32: Programacao ii volume1_v_final

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?

Page 33: Programacao ii volume1_v_final

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

Page 34: Programacao ii volume1_v_final

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.

Page 35: Programacao ii volume1_v_final

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.

Page 36: Programacao ii volume1_v_final

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;

Page 37: Programacao ii volume1_v_final

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

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 uso da Internet estava crescendo vertiginosamente. Foi então que a Sun viu nesta expansão uma oportunidade de usar Oak. A linguagem passaria então a ser voltada para construir aplicações para Web. A linguagem foi rebatizada e passou a se chamar Java, sendo apresentada oficialmente em 1995.

Desde então, Java foi rapidamente adotada pelo mundo, mais rapidamente que qualquer outra linguagem de programação até então. Grandes fornecedores de tecnologia como IBM, Oracle, Netscape, dentre outros, passaram a apoiar Java.

A linguagem evoluiu muito ao longo dos anos. Hoje, mas que uma linguagem, Java pode ser vista como uma plataforma de desenvolvimento e execução de programas em diversas plataformas. Você encontra programas Java na Web, dos telefones celulares, mainframes, cartões inteligentes, dentre outros. Com isso, a linguagem é dividida em 3 grandes segmentos:

1. JEE (Java Enterprise Edition): indicado para aplicações coorporativas, com necessidade gerenciamento de transações, balanceamento de carga, concorrência, 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

Você Sabia?

Você sabia que a linguagem Java tem esse nome devido a um café?

Durante o projeto os participantes tomava muito café, e gostavam principalmente de um proveniente da ilha de Java. No meio do projeto Green, os projetistas foram avisados que já havia uma linguagem com o nome de oak, que inicialmente era o escolhido. Com isso, os projetistas resolveram homenagear a ilha que produzia o café tão apreciado por todos.

Page 38: Programacao ii volume1_v_final

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

Page 39: Programacao ii volume1_v_final

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.

Page 40: Programacao ii volume1_v_final

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

Page 41: Programacao ii volume1_v_final

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.

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

static

É 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 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).

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

main

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). Este é um nome particular de método que indica para o compilador o início do programa.

(String args[])

É o argumento de main e por consequência do programa todo, ele é um vetor (array) de Strings que é formado quando são passados ou não argumentos através 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.

Page 42: Programacao ii volume1_v_final

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.

Page 43: Programacao ii volume1_v_final

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:\Java\bytecode

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

Page 44: Programacao ii volume1_v_final

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/

Page 45: Programacao ii volume1_v_final

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.

Page 46: Programacao ii volume1_v_final

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

Page 47: Programacao ii volume1_v_final

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.

Page 48: Programacao ii volume1_v_final

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.

Page 49: Programacao ii volume1_v_final

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.

Page 50: Programacao ii volume1_v_final

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.