Você está na página 1de 141

AUTOR

Professor Me. Ricardo Bortolo Vieira

● Graduação em Ciência da Computação pela Universidade Estadual de Maringá


(2003).
● Especialização de Engenharia de Software pela Universidade Estadual de Londrina
(2007).
● MBA em Gestão em Saúde Suplementar pela São Marcos (2009).
● Especialização de Gerência de Projetos pela Fundação Getúlio Vargas (2011).
● Mestre em Desenvolvimento de Tecnologias pelo Instituto LACTEC.(2017)
● Doutorando em Informática para PUCPR .
● Gerente de Desenvolvimento de software e profissional do mercado de TI a mais de
15 anos.
● Professor de nível superior da Faculdade Cidade Verde de Maringá (FCV), Universi-
dade Federal do Paraná (UFPR), Faculdade de Engenharia e Inovação Tecnológica
(FEITEP), Fundação Getúlio Vargas (FGV) e Pontifícia Universidade Católica (PUC).
● Experiência na área de Ciência da Computação, com ênfase em Sistemas de Com-
putação e Automação e Robótica, além de experiência em Administração com ênfa-
se em Gerenciamento de Projetos.
● Empreendedor na área de automação industrial e consultoria de processos de indus-
triais e projetos
● Lattes: http://lattes.cnpq.br/5731213234468142
APRESENTAÇÃO DO MATERIAL

Seja muito bem-vindo(a)!


Olá prezado(a) aluno(a), este é o livro Programação Orientada a Objetos, sou o
professor Ricardo Vieira, autor deste material, e o assunto que abordarei no decorrer do
nosso estudo poderá contribuir com sua formação, especialmente a de desenvolvedor (a)
de software. Além disso, este livro auxiliará em sua carreira e abrirá portas para o mundo
dos negócios, mostrando-lhe as vantagens de trabalhar com programação.
Meu objetivo, por meio deste livro, é ensiná-lo o paradigma Orientado a Objetos
voltado a programação, e apresentar algumas técnicas que podem auxiliá-lo neste processo.
Além disso, pretendo deixar claro que o uso correto desse paradigma poderá ajudá-lo a
alcançar os objetivos estratégicos da organização onde trabalha ou auxiliá-lo a colocar em
prática ideia, que por enquanto podem estar arquivadas e aguardando o momento certo
para se tornarem grandes negócios.
Este livro está organizado em quatro unidades, além da introdução e conclusão.
Cada uma delas correspondendo a uma das partes importante na programação orientada
a objetos.
Na primeira unidade, você vai estudar o histórico e conceitos desse paradigma
que nos permite programar de forma mais próxima do nosso pensamento. Além de estudar
sobre a relação da programação orientada a objetos com a análise orientada a objetos, ou
seja, estudando sobre classes, objetos, atributos e instâncias.  
Já na unidade II você poderá constatar os conceitos relacionados ao operador this,
e outros operadores, os construtores para classes e algumas instruções de repetição.
Depois, na unidade III, falaremos sobre comandos em geral para linguagens
orientadas a objeto e aprendendo mais sobre construtores. Trataremos também sobre
conceitos inerentes a Orientação a Objetos como Herança e Polimorfismo. Na unidade IV,
vamos entender melhor sobre encapsulamento de propriedades e a forma correta de se
utilizar um conceito muito poderoso chamado interface. Vamos tratar também sobre captura
e tratamento de exceções e não poderíamos deixar de abordar a programação em um nível
mais macro tratando sobre desenvolvimento em camadas.
Agora, sem perder mais tempos, vamos direto a leitura! Tenha um bom aprendizado.
SUMÁRIO

UNIDADE I....................................................................................................... 5
Programação Orientada a Objetos

UNIDADE II.................................................................................................... 42
Trabalhando com os Métodos e suas Referências

UNIDADE III................................................................................................... 68
Pilares da Orientação a Objetos e seus Comandos

UNIDADE IV................................................................................................. 114


Trabalhando com Interfaces, Tratamento de Erros e Novos
Paradigmas
UNIDADE I
Programação Orientada a Objetos
Professor Mestre Ricardo Vieira

Plano de Estudo:

1. PARADIGMA DA PROGRAMAÇÃO ORIENTADA A OBJETOS


2. CLASSES E OBJETOS
3. O USO DE ATRIBUTOS
4. INSTANCIAÇÃO REFERÊNCIA PARA OBJETOS
5. MENSAGENS ENTRE OBJETOS
6. CONSIDERAÇÕES FINAIS
7. REFERÊNCIAS

Objetivos de Aprendizagem:

● Conceituar e contextualizar os diferentes termos utilizados em Orientação a


Objetos.
● Compreender as características dos métodos Orientação a Objetos.
● Entender os diferentes termos utilizados em Orientação a Objetos.
● Conhecer a evolução dos métodos Orientação a Objetos.

5
INTRODUÇÃO

Caro (a) aluno (a), iniciaremos a primeira unidade do livro Programação Orientado
a Objetos (POO) com uma breve introdução sobre o Paradigma Orientado a Objeto e
a importância da elaboração de um código elegante dentro do projeto de produção de
software.

Em seguida, você verá como os conceitos de Classes e Objetos utilizando classes


predefinidas e suas bibliotecas da linguagem de programação Java, a utilização de estruturas
dinâmicas como listas simplesmente ligadas/encadeadas.

Nesta unidade, também você conhecerá e entenderá os conceitos e termos utilizados


na análise e no projeto Orientado a Objetos (OO). Dentre os conceitos que veremos, estão
o de tipos de dados abstratos, classe, instância, atributo, mensagem, , entre outros. Com
esses conceitos iniciais, você terá uma visão geral sobre OO.

Então, o que estamos esperando? Vamos ao trabalho?

Boa leitura a todos.

UNIDADE I Programação Orientada a Objetos 6


1. PARADIGMA DA PROGRAMAÇÃO ORIENTADA A OBJETOS

A Orientação a Objetos (OO) surgiu de um trabalho acadêmico genial de Keith


Tocher (1967) que formaliza a teoria da simulação no artigo intitulado The Art of Simulation.
Ela foi baseada em modelos matemática e subdivida em três categorias: Discrete Events
Simulation, Continuous Simulation e Monte Carlo Simulation. A categoria Discrete Events
Simulation trabalha com mudanças de estado, relacionamentos e trocas de informações.
Dessa forma, é fácil perceber que onde nossa OO surgiu (NANCE, 1995).  
À medida que os conceitos OO ganharam ampla aceitação durante as décadas
de 1980 e 1990 surgiram muitas opiniões diferentes sobre as respostas corretas a essas
perguntas, mas atualmente há uma visão coerente dos conceitos orientados a objeto. Esta
introdução lhe proporcionará uma rápida visão do tópico e apresentará os conceitos básicos
e a terminologia. (PRESSMAN, 2011).
A principal característica do Paradigma Orientado a Objetos (POO) é uma maior
e melhor expressividade das necessidades do nosso dia a dia. Possibilitando criar uma
unidade de código mais próxima da forma como pensamos e agimos, assim facilitando
o processo de transformação das necessidades diárias para uma linguagem orientada a
objeto.
Assim, Orientação a Objetos é um paradigma de análise, projeto e programação
de sistemas de softwares baseado na composição e interação entre diversas unidades de
software chamadas de objetos.

UNIDADE I Programação Orientada a Objetos 7


Dá-se o nome de Programação Orientado a Objeto ao processo que utiliza uma
linguagem OO. A sigla POO termina se fundindo entre a programação e o paradigma. A
utilização de uma linguagem orientada a objeto somente, em alguns casos, não garante que
se está programando efetivamente orientado a objeto. É importante prover um embasamento
sobre os fundamentos da OO. Todo o conceito tem como finalidade possibilitar e facilitar
a aplicação destes conceitos. O uso correto destes conceitos eleva e facilita o processo
de programação. O ponto de partida para a compreensão de OO é compreender o que é
objeto e seus aspectos envolvidos em sua criação e sua manipulação (PRESSMAN, 2011).
No mercado atual de softwares, grande linguagens de programação como Java,
ASP.NET, CSharp, C++, Python são OO, assim você consegue perceber a importância de
estudar e absorver os conceitos de OO. Neste livro iremos discutir o assunto de OO usando
como base a linguagem JAVA.

1.1. Métodos com Elegância

Antes de conhecer a maneira apropriada de projetar um grande sistema de


software Orientado a Objetos, inclusive a divisão adequada do sistema em classes com
responsabilidades e colaborações convenientes, temos que entender o que torna uma
classe individual elegante. Qual é o papel de uma classe? Que tipo de responsabilidades
ela deve ter? Isto é, quais os dados ela deve manter e o que poderá ser feito com esses
dados e com outros? Em outras palavras, qual deverá ser seu comportamento?
Além disso, uma vez que tivermos tomado essa decisão, como iremos implementar
esse comportamento com os métodos? Comecemos com os métodos. A elegância de um
método está relacionada ao seu tipo de retorno, ao nome dos parâmetros ou ao corpo do
método? Na verdade, está relacionada a todas essas partes. Para nos ajudar a entender
as questões existentes em torno da elegância dos métodos, vamos considerar primeiro um
exemplo simples.

Suponhamos que estivéssemos desenvolvendo uma nova classe DataHolder que,


quando solicitada, deverá inserir novos valores em um array de inteiros, referenciado por
sua variável de instância privada data. Isto é, esse ato de inserção tem que fazer parte
do comportamento da classe. Como resultado, temos de adicionar um ou mais métodos
à classe para executar a inserção. Há vários métodos que poderíamos criar para dar à
classe esse comportamento. Por exemplo, poderíamos criar um método insert( ) que use
como parâmetro o novo valor inteiro a ser inserido e um índice inteiro indicando onde ele

UNIDADE I Programação Orientada a Objetos 8


deverá ser inserido. O método apenas insere o valor no local apropriado do array data. A
alternativa será dividir o processo em três métodos separados, em que o primeiro método,
increaseCapacity( ), aumentará o array, se necessário. O segundo, shift( ), deslocará os
outros inteiros para dar espaço para o novo inteiro. E o terceiro, put( ), deverá inserir o novo
inteiro no local recém liberado. Além disso, poderíamos deixar para o usuário a chamada
aos três métodos individualmente ou criar um método insert( ) adicional que chamasse
esses outros três métodos.

Também poderíamos usar um nome que não fosse “insert” para o método ou alterar
a ordem ou o número de parâmetros. Por exemplo, poderíamos sobrecarregar o método
para que dois valores pudessem ser inseridos ao mesmo tempo. Também poderíamos ter
vários tipos de retorno. O método poderia ter void como tipo de retorno ou, por exemplo,
retornar informações indicando se foi bem sucedido na inserção do novo valor. Qual dessas
opções seria a melhor? Voltaremos continuamente a esse exemplo nesta seção do capítulo
e, no processo, responderemos a essa pergunta e a pergunta mais geral sobre o que torna
um método elegante.

1.2. Convenções de Nomenclatura

Segundo Tucker (2009), vários princípios da criação de software pode nos ajudar a
comparar e julgar as abordagens mencionadas no parágrafo anterior. Um princípio é usar
nomes que revelem a finalidade. Ele será examinado com mais detalhes porque não se
aplica só aos métodos. Pode ser aplicado a qualquer parte do software que use nomes,
inclusive métodos, variáveis, classes e interfaces. Um nome de método deve indicar a
finalidade do método, isto é, o que o método deverá fazer. O nome não deverá indicar como
o método atingirá seu objetivo e sim qual será o objetivo. Um método que não retornar um
valor (um método com tipo de retorno void) deverá ter um nome composto por um verbo
ou um verbo e seu complemento, como print( ) ou setName( ). Nomes vagos como doIt(
) são inadequados. Um método que retornar um valor deverá ter um nome que reflita o
valor que estará sendo retornado, por exemplo, length( ) ou name( ). Esse tipo de método
também poderia ter um verbo e seu complemento como nome. Como convenção pode-se
utilizar a palavra “get” seguida do valor retornado. Por exemplo, um método que retorne o
tamanho de alguma estrutura de dados poderia receber o nome size( ) ou getSize( ). Com
relação ao nosso exemplo DataHolder, o nome insert( ) será satisfatório, pois descreverá
sucintamente o que o método deverá fazer.

UNIDADE I Programação Orientada a Objetos 9


Classes e interfaces deverão ter nomes que reflitam o papel ou a finalidade de
objetos desses tipos. O nome de uma classe será a primeira pista que o leitor tem do papel
real que ela desempenha em um projeto e portanto, vale a pena dedicar algum tempo na
busca de um nome apropriado. Normalmente os nomes de classes são substantivos, como
Date ou ComputerCard. Quase sempre interfaces têm nomes que terminam em “-able”,
como Cloneable ou Iterable (TUCKER, 2009).

Para concluir, as variáveis têm que ser nomeadas apropriadamente para melhorar
a legibilidade. Considere um programa com uma variável chamada nT. Um argumento a
favor de um nome assim seria que ele é curto e, portanto, economiza tempo de digitação
e ajuda a encurtar as linhas de código. Contudo, o nome não é significativo no que diz
respeito a indicar a função da variável e o leitor é forçado a memorizá-la. Por outro lado,
chamar a variável de numberOfThreads ou NumThreads ou até mesmo numThrds em vez
de nT, aumenta drasticamente a facilidade de entender o código.

Uma variável boolean deverá ter um nome apropriado para o valor que representa.
Geralmente não deverá representar a negação de um valor, então, por exemplo, não
deveremos chamar nossa variável de notYetDone, que poderia resultar na necessidade de
expressões como a negativa dupla !notYetDone. Em vez disso, seria melhor chamá-la de
done e usar a expressão !done sempre que notYetDone tivesse de ser usada. É claro que
o nome done também não é ideal, já que a palavra não contém informações suficientes
para ajudar o leitor a entender o papel da variável. O nome da variável deverá informar
que atividade é ou não executada. Por exemplo, se essa variável estiver sendo usada para
indicar que uma imagem gráfica acabou de ser carregada e já pode ser vista, um nome
melhor seria doneLoading. Lembrem-se, nomes ruins não levam apenas a enganos; eles
tornam o sistema inteiro mais difícil de entender, o que vai contra nosso desejo de ter um
software legível conforme trata Tucker (2009) em seu livro de princípios e paradigmas.

1.3. Métodos Coesos

Ainda conforme Tucker(2009), outro princípio da criação de softwares é: “os métodos


devem fazer apenas uma coisa e fazê-la bem”. Isto é, um método não deve executar duas
ou mais tarefas a menos que façam parte de uma mesma ação coesa. Por exemplo, faz
sentido o método insert( ) mencionado acima aumentar o array, mover os outros valores
para dar espaço para o novo valor e adicionar o novo valor, porque tudo isso faz parte de

UNIDADE I Programação Orientada a Objetos 10


uma ação coesa. Por outro lado, um método que tanto insira novos itens em um array data
quanto determine se uma String está na forma de um endereço de e-mail não é coeso. A
principal razão para evitar a criação desse tipo de método é que, com frequência, queremos
executar uma das ações, mas não as duas. Nesse caso, um método que execute as duas
é desnecessário. Um método é muito mais reutilizável quando faz apenas uma coisa. Na
Figura 01 está um exemplo de um método não coeso.

Figura 01. Exemplo de método não coeso. Elaborado pelo autor.

Esse método está claramente tentando fazer duas coisas e usando o flag para
determinar qual delas fazer. Seria melhor termos dois métodos auxiliares separados, como
doThis( ) e doThat( ), nenhum deles precisando de um flag. Uma vez que tivermos esses
métodos, poderemos reescrever o método acima conforme a Figura 02.

Figura 02. Exemplo de método coeso. Elaborado pelo autor.

Agora esse código será aceitável (exceto pelos nomes flag, this e that, que não
revelam a finalidade), já que o método está apenas agindo como uma central de despachos
e, portanto, está fazendo apenas uma coisa e fazendo-a bem.

Um resultado interessante para o princípio da coesão, tratado por Tucker(2009), é


o princípio que um método deverá modificar o estado de um objeto ou de objetos existentes
ou retornar um valor, mas não ambos. Com estado de um objeto, queremos dizer os valores
de suas variáveis de instância. Novamente, o raciocínio por trás desse princípio é o de que,
às vezes, podemos querer modificar o estado de um objeto, mas não retornar um valor,
em outras palavras, pode querer retornar um valor, mas não modificar um objeto. Logo, a
título de reutilização, é melhor separar essas ações em dois métodos separados. Observe
que a adesão rigorosa a esse princípio requer que não haja modificação de código dentro

UNIDADE I Programação Orientada a Objetos 11


de métodos que retornem valores. Por exemplo, um método que informa se um array está
classificado ou revele qual o maior valor do array retorna um valor e, portanto, não deve
modificar o array. Outra maneira de formular esse princípio seria dizendo que métodos que
retornam valores não devem ter efeitos colaterais, e métodos com efeitos colaterais não
devem retornar valores.

Dito isso, observe que temos usado as terminologias “diretrizes” e “princípios” em


vez de “regras”. Ou seja, essas diretrizes devem ser levadas em consideração no projeto
ou implementação de um sistema de software, mas não são regras a serem rigidamente
seguidas conforme descreve Tucker (2009). Em algumas situações, pode ser melhor para
o projeto se ignorarmos um ou mais desses princípios. E alguns códigos legados e de
biblioteca não os seguem. Por exemplo, o pacote java.util tem uma classe Stack com um
método pop( ) que tanto remove o objeto do topo da pilha quanto o retorna. Tecnicamente,
esse comportamento desobedece ao princípio mencionado acima, mas é aceitável porque
é um comportamento sensato nesse caso e, o mais importante, porque esse método vem
sendo usado há anos e alterar seu comportamento agora seria muito pior do que deixar que
ele continue desobedecendo à diretriz .

1.4. Objetos Bem Formados

Aqui, ainda citando Tucker(2009), está outro princípio relativo a métodos elegantes:
“um método não privado deverá manter um objeto em um estado bem formado”. Por
exemplo, suponhamos que você tivesse uma classe com duas variáveis de instância: um
array de inteiros data e um inteiro max, que armazenam o valor máximo do array data. Você
deverá tomar cuidado para não ter métodos na classe que modifiquem o array sem atualizar
também a variável max. É a esse tipo de coerência interna que nos referimos quando
dizemos que uma classe é “bem formada”. Como formular os requisitos de coerência dos
objetos de uma classe? Isto é, como saber se a instância de uma classe está bem formada?
Uma boa maneira é criar uma lista das invariantes da classe. Uma invariante de classe é
uma declaração que fornece os requisitos sobre o estado de instâncias da classe entre
chamadas de método públicas. Um exemplo de invariante de classe é a declaração “O valor
de max e o maior valor do array data deverão ser iguais”. Como outro exemplo, considere a
implementação, apresentada na Figura 03, da classe DataHolder discutida anteriormente.

UNIDADE I Programação Orientada a Objetos 12


Figura 03. Implementação da Classe DataHolder. Elaborado pelo autor.

Observe que o array data está sempre repleto de dados que foram inseridos.
Isto é, nunca haverá locais não usados no array. Essa é uma invariante para objetos
da classe DataHolder. Se a invariante for rompida, poderá ocorrer um comportamento
inesperado. Para evitar isso, os três métodos auxiliares increaseCapacity( ), shift( ) e put( )
foram construídos como privados. Como resultado, os objetos desta classe, poderão ficar
temporariamente mal formados. Por exemplo, após increaseCapacity( ) ter sido chamado,
mas serão restaurados para um estado bem formado, antes de algum método público
retornar. Se increaseCapacity( ) ou shift( ) fossem públicos, qualquer usuário do objeto
poderia chamá-los isoladamente, causando a má formação do objeto.

Para que as invariantes de classe sejam mantidas, é preciso que as variáveis de


instâncias sejam privadas ou finais, se tiverem envolvimento com alguma invariante de

UNIDADE I Programação Orientada a Objetos 13


classe. Caso contrário, outro objeto poderia acidental ou maliciosamente alterar o valor da
variável e gerar o objeto mal formado.

1.5. Tipo Abstrato de Dados

Serra (2003) apresenta a noção de Tipo Abstrato de Dados (TAD), iniciando pela
especificação de um tipo de dado com as suas propriedades fundamentais, de maneira
independente da implementação da linguagem utilizada.
São três passos envolvidos para implementar um tipo abstrato de dados (TAD):
● O primeiro passo será a definição de uma API Java (Application Programming Inter-
face), ou simplesmente interface, que descreverá os métodos que o TAD suportará
e como eles serão declarados e como serão utilizados.
● O segundo passo será a escolha da representação Concreta do TAD que será utili-
zada na implementação. Assim, basicamente dois tipos de representação são intro-
duzidos:
○ Estrutura Estática (com a utilização de arrays);
○ Estrutura Dinâmica (com a utilização de listas ligadas/encadeadas, pilhas,
árvore, etc.).
● E o terceiro passo será a implementação da interface através de uma classe e le-
vando em consideração a representação escolhida no segundo passo.

Poderá existir muitas implementações para todo o TAD, contudo todas as


implementações deverão respeitar a interface definida, conforme trata Serra (2003).

1.5.1. Estruturas

Segundo Serra(2003), precisamos frequentemente agrupar vários elementos e ou


dados num conjunto. A princípio não saberemos o número exato de elementos que serão
agrupados. A cada instante podemos remover ou acrescentar elementos ao conjunto. Dentro
da programação deveremos considerar dois tipos de estruturas que permitirão guardar uma
coleção de elementos, que poderão ser a Estrutura Estática e a Estrutura Dinâmica. Os
elementos poderão ser organizados de maneira distinta. Poderemos destacar, entre as
organizações possíveis:
● Estrutura Linear: Determina que haja entre os elementos da coleção, a existência
de uma determinada ordem. Por exemplo: Primeiro elemento, Segundo elemento, ...
N elemento, Último elemento.

UNIDADE I Programação Orientada a Objetos 14


● Estrutura Hierárquica: É a organização de elementos que poderão ser representa-
das em forma de árvore.
● Estrutura Grafo: É a organização de elementos que serão representadas em forma
de rede.
Neste capítulo serão apresentados exemplos de implementações destas três
estruturas: Linear, Estática e Dinâmica. Começaremos pela Figura 04 apresentando uma
estrutura linear.

Figura 04. Representação da estrutura linear. Elaborado pelo autor.

1.5.2. Estrutura Estática

Ainda segundo Serra(2003), a principal característica da estrutura estática é possuir


um espaço alocado e permanecerá inalterável até antes da sua utilização. Esta estrutura não
deverá conter mais elementos do que foi inicialmente pré-determinado. A Estrutura Estática
será representada através do uso de tabelas, em termos da linguagem de programação
Java. Uma vez alocado um determinado espaço numa tabela, este permanecerá inalterável,
independente das operações de de remoção e inserção dos elementos, mesmo que esta
estrutura não possua nenhum elemento armazenado nela.

Para facilitar a compreensão de vocês, meus caros leitores, será apresentado uma
implementação, na Figura 05, de uma interface denominada estruturaLinear por meio de
uma determinada classe chamada ArrayCircularList. Esta implementação está baseada
na utilização de uma Estrutura Estática, que servirá para guardar os elementos de uma
determinada coleção. A opção foi a utilização de uma estrutura circular.

UNIDADE I Programação Orientada a Objetos 15


1.5.3. Estrutura Dinâmica

Continuando a referência segundo Serra (2003), Uma das principais características


da estrutura dinâmica é que ela poderá sofrer alterações à medida que ocorrer a sua
manipulação através de inserção e remoção de elementos em sua estrutura. A Estrutura
Dinâmica, em sua dimensão, não possuirá limitações, com exceção da limitação física do
espaço de memória do computador, sendo esta a sua única restrição, onde ocorrerá a
execução do algoritmo. A Estrutura Dinâmica será instanciada com a utilização do tipo
de dado que ela fizer a Referencia (apontador). As Estruturas Dinâmicas poderão ser
criadas para fazer a representação das coleções dos elementos com diferentes tipos
de organização. A implementação de uma Estrutura Linear poderá ser realizada com a
utilização de Estruturas Dinâmicas, com a representação de listas simplesmente ligadas,
de listas duplamente ligadas, de listas circulares, etc. Será apresentado na Figura 06, a
implementação de uma interface denominada estruturaLinear, como um exemplo de
utilização destas listas.

Figura 05. Exemplo de implementação uma estrutura estática. Elaborado pelo autor.

UNIDADE I Programação Orientada a Objetos 16


1.5.3.1. Listas simplesmente ligadas/encadeadas

A forma mais simples para a representação de uma coleção de elementos será a


utilização de uma lista encadeada, que juntos formarão uma ordenação linear, conforme
trata Serra (2003). O objeto da classe No fará a representação de cada elemento da coleção.
A ordenação será determinada com o armazenamento da referência em um nó para um
elemento e uma referência, será chamada de próximo, para o próximo nó da coleção.
Conforme será visto na Figura 06.

Figura 06. Representação de Lista Encadeada. Baseado em Serra (2003).

Serra (2003) indica que poderá ser vista como uma ligação ou apontador para
outro nó a referência Próximo dentro de um nó. Serão chamados, respectivamente, de
Cabeça e Cauda da lista o primeiro Elemento (nó) e os últimos Elementos (nós) de uma
lista. A cauda será o Elemento (nó) que terá a referência Próximo igual à null, indicando
o fim da lista. O deslocamento de um Elemento (nó) para outro seguindo a referência
Próximo será conhecido como percorrer a lista ou caminhar na lista. Será conhecida como
uma lista simplesmente encadeada, uma lista encadeada que for definida desta maneira.
Uma lista simplesmente encadeada, diferentemente de uma tabela, não terá tamanho fixo
pré-determinado e alocará ao número de Elementos, os espaços proporcionais a cada
um deles. Na Figura 07, será definida uma classe No, para implementação de uma lista
simplesmente encadeada na linguagem de programação Java.

UNIDADE I Programação Orientada a Objetos 17


Figura 07. Implementação de uma Lista Encadeada em Java. Elaborado pelo autor.

A interface estruturaLinear pode ser implementada usando uma lista simplesmente


encadeada na classe ListaEncadeada conforme mostra a Figura 08.

Figura 08. Implementação de uma Lista Simplesmente Encadeada. Elaborado pelo autor.

UNIDADE I Programação Orientada a Objetos 18


1.5.3.2. Inserir Elemento na Cabeça da Lista

Numa lista simplesmente encadeada podemos inserir ou remover um elemento na


cabeça da lista. Conforme ilustra a sequência de Figuras de 09 a 11.

Figura 09. Antes da inserção de novo nó na Cabeça da Lista. Baseado em Serra (2003).

Figura 10. Inserção de novo nó Cabeça da Lista. Baseado em Serra (2003).

Figura 11. Depois da inserção de novo nó Cabeça da Lista. Baseado em Serra (2003).

UNIDADE I Programação Orientada a Objetos 19


O código para esta operação é descrito na Figura 12.

Figura 12. Código para a inserção de novo nó na Cabeça da Lista. Elaborado pelo autor.

1.5.3.3. Inserir Elemento na Cauda da Lista

Nesta situação Serra (2003) indica que teremos que percorrer todos os elementos
a partir do ponteiro da cabeça até chegar no último Elemento, caso não tenha a referencia
para o último Elemento da lista (ponteiro Cauda). A representação escolhida para a lista,
como nosso exemplo, possui uma variável com a referência para o último Elemento (Cauda).
Esta operação será descrita nas Figuras de 13 a 15.

Figura 13. Antes da inserção de novo nó na Cauda da Lista. Baseado em Serra (2003).

Figura 14. Inserção de novo nó na Cauda da Lista. Baseado em Serra (2003).

UNIDADE I Programação Orientada a Objetos 20


Figura 15. Depois da inserção de novo nó Cauda da Lista. Baseado em Serra (2003).

O código para esta operação é apresentada na Figura 16.

Figura 16. Código para a inserção de novo nó na Cauda da Lista. Elaborado pelo autor.

1.5.3.4. Remoção do Nó

Serra (2003) trata essa situação da seguinte forma - o elemento (nó) da cabeça
ou da Cauda da lista poderá ser removido. A implementação do método seguinte permitirá
remover o Elemento da Cabeça da lista.

Figura 17. Método para a remoção do elemento da Cabeça da Lista. Elaborado pelo autor.

Para a remoção do Elemento da cauda da lista, obrigatoriamente deverá percorrer


cada Elementos da lista, desde a cabeça até ao penúltimo elemento da lista.

UNIDADE I Programação Orientada a Objetos 21


Figura 18. Método para a remoção do elemento da Cauda da Lista. Elaborado pelo autor.

1.5.3.5. Listas Duplamente Encadeada/Ligadas

Deverá existir para cada Elemento (nó) da lista duplamente encadeada, uma
ligação não somente para o próximo Elemento, mas também para o Elemento anterior
da lista. Com esta variante, da lista simplesmente encadeada, permitirá a inserção e a
remoção o Elemento (nó) na cabeça e na cauda da lista. Para implementação deste tipo
de lista, Devemos especificar a classe NoD, composta por Elemento (nó) referência para
o Elemento (nó) seguinte e referência para o Elemento (nó) anterior. Estes são os passos
descritos por Serra (2003) para o tratamento de lista duplamente encadeadas. Além disso,
o código desta classe poderá ser visualizado na Figura 18.

UNIDADE I Programação Orientada a Objetos 22


Figura 18. Método para inserção e a remoção de elementos da Lista Simplesmente Encadeada. Elaborado
pelo autor.

Assim o código para lista dupla é apresentado nas Figuras 19, 20 e 21.

Figura 19. Método para inserção e a remoção de elementos da Lista Duplamente Encadeada. Elaborado
pelo autor.

UNIDADE I Programação Orientada a Objetos 23


Figura 20. Método para inserção e a remoção de elementos da Lista Duplamente Encadeada. (Continua-
ção). Elaborado pelo autor.

Figura 21. Método para inserção e a remoção de elementos da Lista Duplamente Encadeada. (Continua-
ção). Elaborado pelo autor.

UNIDADE I Programação Orientada a Objetos 24


2. CLASSES E OBJETOS

2.1. Classes Predefinidas

Conforme apresenta Sierra (2012), os nomes dos pacotes da linguagem de


programação Java sempre começarão com Java, para pacotes do núcleo da linguagem ou
Javax para as extensões ao núcleo. Será utilizada a instrução de import para identificar e
carregar as classes que precisarmos utilizar em nossas implementações. Sempre antes da
definição das classes é que as instruções import deverão aparecer. Exemplo: import java.
util.Scanner;.
Na linguagem de programação Java, as classes predefinidas serão agrupadas
em categorias de classes conhecidas como pacotes (package), também são chamadas
de bibliotecas de classes Java ou são chamadas ainda de Interface de Programação de
Aplicativos Java (Java API). Na linguagem de programação Java, a Biblioteca (API –
Application Programming Interface), ela será composta por um conjunto de classes do JDK,
que são organizadas em pacotes;
São exemplos de pacotes Java apresentados por Sierra (2012):
● java.util: Contém a estrutura de coleções, classes de coleção herdadas, modelo de
evento, facilidades de data e hora, internacionalização e classes de utilidade diver-
sas (um tokenizer de string, um gerador de números aleatórios e uma matriz de bits).
● java.net: Fornece as classes para implementar aplicativos de rede (sockets e URLs);
● java.lang: Fornece classes que são fundamentais para o design da linguagem de
programação Java. Tipos e funcionalidades básicas da linguagem. Incluindo entre
outras, as classes String, Math, Integer e Thread. Ela será importada automatica-

UNIDADE I Programação Orientada a Objetos 25


mente em seus programas Java;
● java.io: Fornece entrada e saída do sistema através de fluxos de dados, serialização
e sistema de arquivos. São classes para escrita e leitura em arquivos;
● java.awt: Contém todas as classes para criar interfaces com o usuário e pintar grá-
ficos e imagens. São componentes gráficos originalmente da linguagem de progra-
mação Java (Abstract Window Toolkit);
● java.applet: Fornece as classes necessárias para criar um applet e as classes que
um applet usa para se comunicar com seu contexto de applet. São classes específi-
cas para tratamento de applets;
● javax.swing: Fornece um conjunto de componentes “leves” (a toda linguagem Java)
que, no grau máximo possível, funcionam da mesma maneira em todas as platafor-
mas. É um framework da plataforma Java para melhoramentos à biblioteca AWT;
(Fonte: https://docs.oracle.com/javase/8/docs/api/overview-summary.html).

2.1.1. Biblioteca java.lang

Schildt (2013) trata sobre a biblioteca java.lang como sendo importada


automaticamente para todos os programas. Ela contém classes e interfaces que são
fundamentais para praticamente toda a programação Java. É o pacote Java mais
amplamente usado e todos os programadores de Java devem ter um conhecimento geral
do que ele fornece. O pacote java.lang inclui as classes de nível superior apresentadas na
Tabela 01.

Tabela 01. Pacote java.lang. Elaborado pelo autor.

As interfaces de nível superior definidas por java.lang são as mostradas na Tabela 02.

UNIDADE I Programação Orientada a Objetos 26


Tabela 02. Interfaces de nível superior definidas por java.lang. Elaborado pelo autor.

Como podemos ver, as classes e interfaces de java.lang definem um grande número


de funcionalidades. Nem todas as partes são amplamente usadas, ou usadas por todos
os programadores. Por exemplo, algumas classes, como StrictMath e Compiler, são mais
aplicáveis a situações específicas.

2.1.2. Bibliotecas AWT e Swing

Segundo Pereira (2017), será fornecido pela biblioteca AWT todas as classes para a
criação de interfaces com o usuários, imagens e pintará gráficos. Ela é uma interface gráfica
de usuário ( Graphical User Interface - GUI). Ela delegará para a Interface Gráfica de Usuário
(GUI) da plataforma nativa (Windows, Linux, Mac) a criação, estilo e comportamento.
Com o seu lema “Write once, run anywhere” (“Escreva uma vez, execute em
qualquer lugar”), o estilo será o mesmo da plataforma, se fizermos uma caixa de texto,
por exemplo, no Windows ou Linux, que atenderá à promessa de portabilidade do Java,
conforme apresenta Schildt (2013).

Para aplicações simples, o sistema funciona perfeitamente. O problema será para


as aplicações mais complexas, as mudanças sutis nos comportamentos de Textfields, scrolls
ou menus poderão causar alterações na experiência do usuário e até causar problemas
diferentes em cada sistema, acabando com a ideia de portabilidade.
Com o pacote “java.awt”, biblioteca AWT foi introduzida no Java 1.0.
Logo depois, como uma extensão, é que a biblioteca Swing foi introduzida na
versão do Java 1.1 e também como parte do pacote padrão na versão do Java 1.2, dentro
do pacote “javax.swing”.

A biblioteca Swing não delegará a criação, estilo e comportamento da interface


gráfica de usuário (GUI) para a plataforma nativa, mas ela tomará para si este trabalho,
cumprindo o objetivo de portabilidade.
A biblioteca Swing é uma biblioteca que complementa o pacote AWT.

UNIDADE I Programação Orientada a Objetos 27


No exemplo da Figura 22, as classes terão pelo menos três linhas com a diretiva
import apontando para pacotes de classes externas, conforme as declarações seguintes:
● import java.awt.*; => permite a utilização de diversas classes do pacote awt, além
de possuir uma série de constantes numéricas.
● import java.awt.event.*; => usado para o processamento dos eventos que ocorrem
na janela, tais como clique do mouse.
● import javax.swing.*; => permite a utilização de diversas classes do pacote swing.

Figura 22. A sequência dos exemplos import java.awt.*; import java.awt.event.*; import java.awt.event.*;
import javax.swing.*; Elaborado pelo autor.

2.1.3. Biblioteca java.applet

“Os applets diferem dos tipos de programa mostrados nos exemplos anterio-
res. Eles são programas pequenos projetados para transmissão pela Internet
e serem executados dentro de um navegador. Já que a máquina virtual Java
se encarrega da execução de todos os programas Java, inclusive applets,
oferecem uma maneira segura de baixar e executar dinamicamente progra-
mas pela Web.”( SCHILDT, 2015, p.499).

Há dois tipos gerais de applets: os baseados apenas no Abstract Window Toolkit


(AWT) e os baseados em Swing. Ambos dão suporte à criação de uma interface gráfica
de usuário (GUI). AWT é o kit de ferramentas de GUI original e Swing é a alternativa leve
e moderna de Java. Segue um exemplo de um Applet simples apresentada na Figura 23.

UNIDADE I Programação Orientada a Objetos 28


Figura 23. Exemplo de um Applet simples baseado em AWT. Elaborado pelo autor.

2.1.4. Biblioteca java.net:

Ainda conforme Schildt (2013), java foi projetada para atender às necessidades
do ambiente de programação da Internet. Portanto, não deve surpreender o fato que a
linguagem dá amplo suporte à rede em sua biblioteca de APIs. O principal pacote de rede
de Java é o java.net. Ele fornece classes que permitem que um aplicativo acesse recursos
de rede de maneira conveniente e eficaz.

É necessário enfatizar que rede é um assunto avançado. Além disso, é um assunto


muito extenso e, às vezes, complexo. Uma discussão sobre rede pode facilmente envolver
vários outros tópicos, como detalhes relacionados a protocolos e à arquitetura geral da
Internet, que não fazem parte do escopo deste livro.

O conceito básico do suporte Java ao uso de rede é o soquete. Um soquete identifica


uma extremidade em uma rede. Ele é à base das redes, porque permite que um único
computador atenda muitos clientes diferentes ao mesmo tempo e forneça vários tipos de
informações diferentes. Isso é feito com o uso de uma porta, que é um soquete numerado
em uma máquina específica. Diz-se que um processo de servidor está “escutando” uma
porta até um cliente se conectar a ela. Um servidor pode aceitar vários clientes conectados
ao mesmo número de porta, mas cada sessão é exclusiva.

2.1.5. Biblioteca java.io

Conforme Silveira (2006), a parte que controlará a entrada e saída de dados,


conhecido como io, da mesma maneira como em todas as bibliotecas em Java, será
também orientada a objetos. Ela usará os principais conceitos de utilização de interfaces,
de polimorfismo e das classes abstratas.

UNIDADE I Programação Orientada a Objetos 29


A ideia atrás da utilização do polimorfismo no pacote java.io, será a utilização para
toda e qualquer operação de fluxos de entrada (InputStream) e de saída (OutputStream),
referente a um arquivo, a uma conexão remota via soquete, a um campo blob do banco
de dados, ou até mesmo às entrada e saída padrão de um programa , normalmente os
teclados e os consoles.

Na linguagem de programação Java as classes abstratas InputStream e


OutputStream definirão, respectivamente, o padrão de comportamento dos fluxos. Será
possível ler bytes em um fluxo de entrada e escrever bytes no fluxo de saída.

Pode ser exibida a grande vantagem dessa abstração, em um método qualquer


que implemente uma classe OutputStream, que receberá como argumento para escrever
um fluxo de saída.

O método está escrevendo onde? Não será necessário saber e isso também não
importará, porque quando o sistema realmente precisar escrever em um arquivo ou em um
soquete, bastará chamar esse mesmo método, já que ele aceitará qualquer classe “filha”
de OutputStream.

2.1.6. Biblioteca java.util:

o pacote java.util define classes e interfaces que atendem várias tarefas comumente
encontradas quando se programa. Por exemplo, ele contém o Collections Framework. O
Collections Framework é um dos subsistemas mais poderosos do Java e dá suporte a uma
sofisticada hierarquia de interfaces e classes que gerenciam grupos de objetos. O pacote
java.util também fornece várias classes utilitárias, inclusive as que formatam dados para
saída, leem dados formatados e trabalham com data e hora. Como java.util dá suporte a
um conjunto tão amplo de funcionalidades, é um pacote muito extenso.

O pacote java.util é muito grande, mas seu tamanho é gerenciável porque as


classes e interfaces que compõem o Collections Framework podem ser examinadas
separadamente, como um grupo.

UNIDADE I Programação Orientada a Objetos 30


3. O USO DE ATRIBUTOS

Os atributos são pertencentes à classe, eles podem ser do tipo primitivo ou


referência (objetos), os seus modificadores podem ser: public, private, protected ou default.
O ciclo de vida destes atributos está vinculado ao ciclo de vida da classe.

Um carro, além de ter a capacidade de realizar tarefas, também tem atributos, como
cor, número de portas, quantidade de gasolina no tanque, velocidade atual e registro dos
quilômetros totais dirigidos (isto é, a leitura do odômetro). Assim como suas capacidades,
os atributos do carro são representados como parte do seu projeto nos diagramas de
engenharia (que, por exemplo, incluem um odômetro e um medidor de combustível). Ao
dirigir um carro real, esses atributos são incorporados a ele. Cada carro mantém seus
próprios atributos. Cada carro sabe a quantidade de gasolina que há no seu tanque, mas
desconhece quanto há no tanque de outros carros.

Um objeto, da mesma forma, tem atributos que ele incorpora à medida que é usado
em um programa. Esses atributos são especificados como parte da classe do objeto. Por
exemplo, um objeto conta bancária tem um atributo saldo que representa a quantidade de
dinheiro disponível. Cada objeto conta bancária sabe o saldo que ele representa, mas não
os saldos de outras contas bancárias. Os atributos são especificados pelas variáveis de
instância da classe.

UNIDADE I Programação Orientada a Objetos 31


No encapsulamento, as classes e seus objetos encapsulam, isto é, contêm seus
atributos e métodos. Os atributos e métodos de uma classe (e de seu objeto) estão
intimamente relacionados. Os objetos podem se comunicar entre si, mas eles em geral
não sabem como outros objetos são implementados, os detalhes de implementação
permanecem ocultos dentro dos próprios objetos.

3.1. Continuando Com Atributos

As variáveis do tipo atributo, diferentemente das variáveis temporárias (declaradas


dentro de um método), recebem um valor padrão. No caso numérico, pode ser zero, no
caso de boolean, pode ser false. Você também pode dar valores default, como apresentado
na Figura 24.

Figura 24. Exemplo de atributos da classe Conta. Elaborado pelo autor.

Nesse caso, quando você criar uma conta, seus atributos já estão “populados”
com esses valores colocados. Imagine que comecemos a aumentar nossa classe Conta e
adicionar nome, sobrenome e CPF do cliente dono da conta. Teríamos muitos atributos. E
se você pensar bem, uma Conta não tem nome, nem sobrenome nem CPF, quem tem esses
atributos é um Cliente. Então podemos criar uma nova classe e fazer uma composição.
Seus atributos também podem ser referências para outras classes. Suponha as seguintes
classes Cliente e Conta apresentado nas Figuras 25 e 26.

Figura 25. Exemplo de atributos da classe Cliente. Elaborado pelo autor.

UNIDADE I Programação Orientada a Objetos 32


Figura 26. Exemplo de referência de atributos da classe Conta. Elaborado pelo autor.

E dentro do main da classe de teste como mostra a Figura 27.

Figura 27. Exemplo de referência de atributos dentro do main da classe de teste. Elaborado pelo autor.

Aqui, simplesmente houve uma atribuição. O valor da variável c é copiado para o


atributo titular do objeto ao qual minhaConta se refere. Em outras palavras, minhaConta
tem uma referência ao mesmo Cliente que c se refere, e pode ser acessado através de
minhaConta.titular.

Você pode realmente navegar sobre toda essa estrutura de informação, sempre
usando o ponto: Cliente clienteDaMinhaConta = minhaConta.titular; clienteDaMinhaConta.
nome = “Luke”; Ou ainda, pode fazer isso de uma forma mais direta e até mais elegante:
minhaConta.titular.nome = “Luke”;

Um sistema orientado a objetos é um grande conjunto de classes que vai se


comunicar, delegando responsabilidades para quem for mais apto a realizar determinada
tarefa. A classe Banco usa a classe Conta que usa a classe Cliente, que usa a classe
Endereco. Dizemos que esses objetos colaboram, trocando mensagens entre si. Por isso
acabamos tendo muitas classes em nosso sistema e elas costumam ter um tamanho
relativamente curto.

UNIDADE I Programação Orientada a Objetos 33


4. INSTANCIAÇÃO REFERÊNCIA PARA OBJETOS

No contexto de uma atribuição, e conforme Deitel (2008), o operador new tem esta
forma geral: var_classe = new nome_classe(lista_arg); O operador new é o responsável
pelo processo de instanciação do objeto, representando uma forma extremamente simples
de atribuir valores default a um objeto.
A declaração: Televisor tv = new Televisor(); pode ser lida como: construa o objeto
tv (do tipo Televisor) com valores default. Como o próprio nome diz, o método construtor é
o responsável por construir um objeto com determinados valores.
Se uma classe não definir seu próprio construtor, new usará o construtor padrão
fornecido por Java. Logo, new poderá ser usado para criar um objeto de qualquer tipo de
classe. O operador new retornará uma referência ao objeto recém-criado, que (nesse caso)
será atribuído a var-classe.

Já que a memória é finita, e conforme Deitel (2008), é possível que new não
consiga alocar memória para um objeto por não existir memória suficiente. Se isso ocorrer,
haverá uma exceção de tempo de execução. Para os exemplos de programa deste livro,
não precisamos nos preocupar em ficar sem memória, mas temos que considerar essa
possibilidade em programas do mundo real que escrevermos ou quando desenvolvemos
para dispositivos embarcados com baixa quantidade de memória.

UNIDADE I Programação Orientada a Objetos 34


4.1. Acessando objetos por referências

Quando declaramos uma variável para associar a um objeto, na verdade, essa


variável não guarda o objeto, e sim uma maneira de acessá-lo, chamada de referência. É
por esse motivo que, diferente dos tipos primitivos como int e long, precisamos dar new
depois de declarada a variável, conforme apresenta a Figura 28.

Figura 28. Exemplo de referência de objeto utilizando new. Elaborado pelo autor.

O correto aqui é dizer que c1 se refere a um objeto. Não é correto dizer que c1
é um objeto, pois c1 é uma variável referência, apesar de que, depois de um tempo, os
programadores Java falarem “Tenho um objeto c do tipo Conta”, mas apenas para encurtar
a frase “Tenho uma referência c a um objeto do tipo Conta”. Basta lembrar que, em Java,
uma variável nunca será um objeto. Não há, no Java, uma maneira de criarmos o que é
conhecido como “objeto pilha” ou “objeto local”, pois todo objeto em Java, sem exceção, é
acessado por uma variável referência, assim como Deitel (2008) trata em seu livro.

UNIDADE I Programação Orientada a Objetos 35


5. MENSAGENS ENTRE OBJETOS

Agora vamos definir outro conceito em OO, assim como menciona Jacobi (2006):
mensagens entre objetos. Já aprendemos que um objeto pode possuir diversos métodos
definidos em sua classe. Em uma aplicação real é muito comum que existam diversos tipos
de objetos e que um objeto necessite realizar uma tarefa que já está definida em outro
objeto, ou seja, numa aplicação poderá haver comunicação e interação entre objetos por
meio de mensagens. Em outras palavras, um objeto X pode necessitar de um procedimento
(método) já definido em um objeto Y. Para realizar esse processo, o objeto X solicita ao
objeto Y que execute o método, ou seja, uma mensagem nada mais é do que o fato de um
objeto chamar um método de outro objeto (ou ainda um método estático de uma classe).

Vamos tentar elucidar com um exemplo. Digamos que um objeto “gerente” precise
enviar um e-mail. Ele não sabe como fazer isso, porém o objeto “email” sabe. Então, o
objeto “gerente” solicita ao “email” que faça isso por ele. Em orientação a objetos, quando
um objeto X solicita a um objeto Y que execute um de seus métodos, diz-se que o objeto
X enviou uma mensagem ao objeto Y. Uma mensagem pode conter parâmetros que são
valores enviados de um objeto a outro, quando um método for invocado. Observe a Figura
29, em que o objeto “gerente” envia uma mensagem ao objeto “email” (invocando o método
enviar). Serão enviados quatro parâmetros: de, para, assunto e mensagem. Esse padrão
do envio de mensagens é definido pela UML e pode ser encontrado, por exemplo, em
diagramas de comunicação e sequência.

UNIDADE I Programação Orientada a Objetos 36


Figura 29. Mensagem do objeto gerente para o objeto email. Elaborado pelo autor.

O processo de comunicação entre os objetos “gerente” e “email” poderá ser assim


descrito:
1. O objeto “gerente” solicita ao objeto “email” o envio de e-mail pelo método
“enviar” contido em “email”, e fornece os parâmetros adequados;
2. O objeto “email” envia o e-mail usando os dados recebidos de “gerente”;
3. Nesse caso o objeto “email” não fornecerá nenhum retorno para o objeto
“gerente” (veja a palavra void adicionada ao final da mensagem), mas isso
poderia ser diferente e o objeto “email” poderia retornar uma mensagem, por
exemplo, informando se houve sucesso ou não no envio.

5.1. Relação hierárquica entre chamadas de método

Como você sabe, e tratado por Jacobi (2006), um método será invocado por uma
chamada de método e quando o método chamado terminar sua tarefa, ele retornará o
controle e possivelmente um resultado para o chamador. Uma analogia a essa estrutura de
programa é a forma hierárquica de gerenciamento, ilustrado na Figura 30 e apresentado
a seguir: Um chefe (o chamador) solicita que um trabalhador (o método chamado) realize
uma tarefa e informe (retorne) os resultados depois de completar a tarefa. O método chefe
não tem conhecimento sobre como o método trabalhador realiza suas tarefas designadas.
O trabalhador também poderá chamar outros métodos trabalhadores, sem que o chefe
saiba. Essa “ocultação” dos detalhes de implementação promove a boa engenharia de
software. A Figura 30 mostra também o método chefe se comunicando com vários métodos
trabalhadores de uma maneira hierárquica. O método chefe divide as responsabilidades
entre os vários métodos trabalhadores. Aqui, trabalhador1 atuará como um “método chefe”
para trabalhador4 e trabalhador5.

UNIDADE I Programação Orientada a Objetos 37


Figura 30. Relacionamento hierárquico de método trabalhador / método chefe. Elaborado pelo autor.

REFLITA

A maior parte da criatividade é uma transição de um contexto para outro, onde as


coisas são mais surpreendentes. Há um elemento de surpresa, e especialmen-
te na ciência, muitas vezes há risos que vão junto com o “Aha”. A arte também tem
esse elemento. Nosso trabalho é nos lembrarmos de que existem mais contex-
tos do que aquele em que estamos - o que achamos ser realidade. (Alan Kay).

Referência: https://citacoes.in/citacoes/1923990-alan-kay-our-job-is-to-remind-us-that-
-there-are-more-contex/

UNIDADE I Programação Orientada a Objetos 38


SAIBA MAIS
QUALIFICAÇÃO DE SOFTWARES

Como pode ser qualificado um software? É muito simples definir isso pelo tempo de de-
senvolvimento ou pela excelência na programação. Existem casos de desenvolvimento
de softwares em que o analista ouve todas as informações e apresenta uma solução,
quase que “surreal”. Algo que poderá resolve perfeitamente o que foi solicitado. Olhando
assim, a sensação que temos parece que o atendimento foi excepcional, contudo, na
maioria das vezes, os programas feitos neste formato não atendem a real necessidade
dos clientes.
Não devemos julgar o cliente por não apresentar de forma assertiva as suas necessida-
des. E a consequência disso tudo é a perda de investimento financeiro e de tempo em
um projeto que não vai atender as suas necessidades. Casos assim são muito comuns
de acontecer, é muito provável que você já tenha vivenciado ou ouvido falar sobre isso.
Esse tipo de problema não é exclusivo do desenvolvimento de softwares, é algo que
ocorre com frequência no mercado, em geral. Para provar isso, basta surgir a necessi-
dade de um serviço, em sua casa ou trabalho, em que não tenha nenhum conhecimento
do processo, como consertar uma porta, uma janela ou uma infiltração na parede. A
solução só vem quando um profissional qualificado está mais preocupado em satisfazer
o cliente do que resolver exclusivamente o problema apresentado. Os profissionais que
mantêm esse tipo de procedimento de atendimento vão sendo substituídos aos poucos.
Na rotina diária de um programador, normalmente, o início do projeto vem de um conver-
sa informal e só lá na primeira apresentação, depois de um grande tempo de dedicação,
é que o cliente consegue esclarecer ainda de forma abstrata com frases como “não é
bem isso que eu queria”. Outro caso comum que acontece, pela falta de alinhamento,
são as solicitações do cliente, ir aumentando durante o processo de desenvolvimento
e como nada está estabelecido de forma clara no início do trabalho, você poderá até
prolongar o projeto, mas, possivelmente, não atenderá todas as necessidades do seu
cliente.
Lembrando que cliente não tem obrigação de entender de programação e que a preo-
cupação deverá ser do programador, de atender o cliente e não o contrário. Um bom
profissional deve fazer uso de uma excelente interpretação às necessidades do cliente
e oferecer não o que ele está pedindo, mas sim o que realmente vai suprir sua neces-
sidade.
(Fonte o autor)

UNIDADE I Programação Orientada a Objetos 39


CONSIDERAÇÕES FINAIS

Nesta unidade, aprendemos que o Paradigma Orientado a Objeto (OO) nos propicia
a elaboração de um código elegante dentro de um projeto de produção de software. Já o
projeto é o resultado do refinamento da análise e considerar os detalhes da implementação,
tal como a linguagem de programação a ser utilizada, que poderá ser Java, CSharp, C++,
Python, ASP.NET, dentro do contexto OO.
Juntos pudemos nos familiarizar com o conceito de Orientação a Objetos, que
é um paradigma para o desenvolvimento de aplicações, ou seja, é uma estratégia de
desenvolvimento de software que organiza o software como uma coleção de objetos, que
contém tanto a estrutura dos dados como o comportamento deles.
Você pode verificar que os métodos coesos, dentro de um projeto orientado a
objetos, devem fazer apenas uma coisa e fazê-la bem. Isto é, um método não deve executar
duas ou mais tarefas, a menos que façam parte de uma mesma ação coesa. Outro princípio
relativo a métodos elegantes que você pode verificar foi que um método não privado deverá
manter um objeto em um estado bem formado.
Você pode verificar as características dos principais métodos OO e foi possível
verificar os tipos abstratos de dados, os dois tipos de estruturas que permitem guardar uma
coleção de elementos: Estrutura Estática e Estrutura Dinâmica.
Você pode verificar os principais métodos, visualizar as suas características e entrar
em contato com os conceitos de OO, em que pode aprender sobre objetos, abstração,
classes, operações, atributos, instância, dentre outros.
Por fim, você pode verificar que um objeto pode possuir diversos métodos definidos
em sua classe. Em uma aplicação real é muito comum que existam diversos tipos de
objetos e que um objeto necessite realizar uma tarefa que já está definida em outro objeto,
ou seja, numa aplicação poderá haver comunicação e interação entre objetos por meio de
mensagens.
A partir dos conceitos que foram abordados nesta unidade, você pode ter uma
visão geral sobre a Programação Orientada a Objetos.
Estaremos juntos na próxima unidade.
Até lá!

UNIDADE I Programação Orientada a Objetos 40


MATERIAL COMPLEMENTAR

LIVRO
• Título: Java como Programar.
• Autor: Paul Deitel e Harvey Deitel.
• Editora: Pearson Education do Brasil Ltda.
• Sinopse: Java: como programar, 10ª edição, fornece uma
introdução clara, simples, envolvente e divertida à programação
Java com ênfase inicial em objetos. Destaques incluem: rica
cobertura dos fundamentos com exemplos reais; apresentação
com ênfase inicial em classes e objetos; uso com Java™ SE
7, Java™ SE 8 ou ambos; Java™ SE 8 abordado em seções
modulares opcionais; lambdas, fluxos e interfaces funcionais
usando métodos padrão e estáticos do Java SE 8; Swing e GUI do
JavaFX: elementos gráficos e multimídia; conjunto de exercícios
“”Fazendo a diferença””; tratamento de exceções integrado;
arquivos, fluxos e serialização de objetos; concorrência para
melhor desempenho com multiprocessamento; o livro contém
o conteúdo principal para cursos introdutórios; outros tópicos:
recursão, pesquisa, classificação, coleções genéricas, estruturas
de dados, multithreading, banco de dados (JDBC ™ e JPA).

FILME/VÍDEO
• Título: Curso de Java SE
• Ano: 2018
• Sinopse: Neste curso de Java avançado irá nos aprofundar em
tópicos de programação que ajudam você a entender os conceitos
mais avançados de Java. Isso significa que o programador já
precisa ter conhecimentos prévios da linguagem Java, bem como
dos seus recursos, lógica de programação, depuração de código,
IDEs, dentre outros conceitos básicos de programação. Dentre
os tópicos avançados que iremos cobrir neste curso, destacam-
se: Java Avançado; programação genérica, estruturas de dados
sequenciais e associativas, estruturas de dados clássicos,
classificação e pesquisa, tratamento de exceções, programação
de GUI com acesso a rede usando Swing e uma visão geral de
multithreading. Você também vai explorar os Applets Java, entrada
e saída avançadas, strings mais avançadas, expressões regulares,
gráficos Java, manipulação de arquivos e, finalmente, fechando
com um olhar mais crítico e profundo sobre a IDE Eclipse.

• Link do vídeo:
https://www.devmedia.com.br/curso/curso-java-se/423

UNIDADE I Programação Orientada a Objetos 41


UNIDADE II
Trabalhando com os Métodos e suas
Referências
Professor Mestre Ricardo Vieira

Plano de Estudo:

1. USO DA PALAVRA RESERVADA this


2. CONSTRUTORES
3. VISÃO GERAL DOS OPERADORES
4. INSTRUÇÕES DE REPETIÇÕES
5. CONSIDERAÇÕES FINAIS
6. REFERÊNCIAS

Objetivos de Aprendizagem:

● Conceituar e contextualizar a importância da utilização da palavra reservada this.


● Compreender os tipos de construtores e sua utilização.
● Apresentar uma visão geral dos operadores.
● Estabelecer a importância das instruções de repetições.

42
INTRODUÇÃO

Caro (a) aluno (a), iniciaremos a segunda unidade do livro Programação Orientado
a Objetos. Nesta unidade iremos nos aprofundar mais ainda sobre os conceitos OO e
v. poderá estudar o uso da palavra reservada this. Poderá também ver como a palavra
reservada this será usada para a autorreferência, com atributos e métodos estáticos.

Na sequência, será apresentado, os tipos de construtores e sua utilização. Será


possível ver que o método construtor será responsável por alocar espaço na memória para
a manipulação do objeto e poderá conter também a chamada para outros métodos. Será
apresentado o construtor default e as regras para se escrever um método construtor.

Em seguida, será apresentada uma visão geral dos operadores e suas estruturas.
Você verá que para tratar situações em que o fluxo de execução do programa deverá
ser alterado, Java fornecerá um amplo conjunto de estruturas condicionais, de exceção
e repetição. Você poderá estudar as estruturas condicionais usados em Programação
Orientada a Objetos, que são if-else e switch-case. Essas duas estruturas de desvio
existentes na linguagem possibilitam executar diferentes trechos de um programa com
base em certas condições.

Nesta unidade, também será apresentado os conceitos a respeito das instruções


de repetições. Também chamados de looping, formam uma importante estrutura nas
linguagens de programação por possibilitarem a repetição da execução de um bloco de
instruções em um programa.

Tenha um bom aprendizado e um excelente aproveitamento.


Então vamos lá!
Bons estudos!

UNIDADE II Trabalhando com os Métodos e suas Referências 43


1. USO DA PALAVRA RESERVADA this

Segundo Goodrich (2013), o this é uma palavra reservada que é usada para a
autorreferência. Esta situação ocorrerá quando quisermos referenciar a métodos e atributos
da própria classe e objeto. Embora seja possível usar o this com atributos e métodos
estáticos, será mais usual utilizá-lo com membros de instância. Mais especificamente ainda,
com atributos.

O não uso em membros estáticos será simples: estes já pertencem à classe e só


existirá uma versão deles. Já com atributos de instância, cada objeto, guardará seu próprio
estado neles, e o uso do this poderá ajudar a diferenciar, por exemplos, parâmetros que
possam vir a ter o mesmo nome dos atributos.

1.1. Referenciando Membros Do Objeto Atual Com A Referência this

Cada objeto poderá acessar uma referência a si própria, com a palavra chave this
(às vezes chamada de referência this). Quando um método de instância for chamado para
um objeto particular, o corpo do método utilizará implicitamente a palavra-chave this para
referenciar as variáveis de instância do objeto e outros métodos. Isso permite que o código
da classe saiba qual objeto deve ser manipulado. Você também poderá usar a palavra
chave this explicitamente no corpo do método de uma instância, assim trata Deitel (2017).

UNIDADE II Trabalhando com os Métodos e suas Referências 44


Agora demonstraremos o uso implícito e explícito da referência this (Figura 31).
Esse exemplo é o primeiro em que declaramos duas classes em um único arquivo, a classe
ThisTest é declarada nas linhas 2 a 9 e a classe SimpleTime, nas linhas 12 a 45. Isso
foi feito para demonstrar que, quando você compilar um arquivo .java que contenha mais
de uma classe, o compilador produzirá um arquivo separado da classe com a extensão
.class para cada classe compilada. Nesse caso, dois arquivos separados serão produzidos:
SimpleTime.class e ThisTest.class. Quando um arquivo de código-fonte (.java) contiver
múltiplas declarações de classe, o compilador irá inserir ambos os arquivos de classe para
essas classes no mesmo diretório.

Observe também na Figura 31, que só a classe ThisTest é declarada public. Um


arquivo de código-fonte pode conter somente uma classe public, caso contrário, um erro de
compilação ocorrerá. As classes não public só poderão ser utilizadas por outras classes no
mesmo pacote. Assim, nesse exemplo, a classe SimpleTime só pode ser usada pela classe
ThisTest.

A classe SimpleTime (linhas 12 a 45) declara três variáveis de instância private:


hour, minute e second (linhas 14 a 16). O construtor da classe (linha 21 a 26) recebe três
argumentos int para inicializar um objeto SimpleTime. Mais uma vez, utilizamos nomes
de parâmetro para o construtor (linha 21) que são idênticos aos nomes das variáveis de
instância da classe (linhas 14 a 18). Assim, usamos a referência this para nos referirmos às
variáveis de instância nas linhas 23 a 25.

O método buildString (linhas 29 a 34) retorna uma String criada por uma instrução
que utiliza a referência this explícita e implicitamente. A linha 34 usa-a explicitamente
para chamar o método toUniversalString. A linha 32 utiliza-a implicitamente para chamar
o mesmo método. Ambas as linhas realizam a mesma tarefa. Em geral, você não utilizará
this explicitamente para referenciar outros métodos dentro do objeto atual. Além disso, a
linha 44 no método toUniversalString utiliza explicitamente a referência this para acessar
cada variável de instância. Isso não é necessário aqui, porque o método não tem variáveis
locais que sombreiam as variáveis de instância da classe.

O método main (linhas 4 a 8) da classe ThisTest demonstra a classe SimpleTime. A


linha 6 cria uma instância da classe SimpleTime e invoca seu construtor. A linha 7 invoca o
método buildString do objeto e então exibe os resultados.

UNIDADE II Trabalhando com os Métodos e suas Referências 45


Figura 31. Exemplo de this utilizado implícita e explicitamente como uma referência a
membros de um objeto. Elaborado pelo autor.

UNIDADE II Trabalhando com os Métodos e suas Referências 46


2. CONSTRUTORES

O operador new é o responsável pelo processo de instanciação do objeto,


representando uma forma extremamente simples de atribuir valores default a um objeto.
Como o próprio nome diz, o método construtor é o responsável por construir um objeto com
determinados valores.
O método construtor será responsável por alocar espaço na memória para
a manipulação do objeto e poderá conter também a chamada para outros métodos,
possibilitando a criação de objetos mais complexos. Na criação de janelas gráficas (frames),
por exemplo, o método construtor pode definir todas as propriedades dos componentes
visuais do frame (cor do formulário, tamanho dos botões etc.), conforme descreve Furgeri
(2015).

2.1. Construtor default

“Se um construtor não for declarado, será assumido um construtor default da


linguagem Java, em que as variáveis serão inicializadas com os conteúdos
default (variáveis numéricas recebem zero, valores lógicos recebem false e
objetos recebem null). Quando declarado, ele deverá possuir, obrigatoria-
mente, sempre o mesmo nome (idêntico) da classe em que se está locali-
zado. Dependendo das necessidades, uma classe pode conter de zero a N
construtores declarados.” (Furgeri, 2015 p. 115)

Toda a classe Java deverá ter um construtor. Quando não declaramos o construtor,
default será inicializado automaticamente pelo Java. Mas existem casos que se faz

UNIDADE II Trabalhando com os Métodos e suas Referências 47


necessário à declaração explícita dos construtores. O Construtor não poderá ser herdado.
Para chamá-lo a partir de uma subclasse usamos a referência super.  

Para escrever um construtor, devemos seguir algumas regras:


1. O nome do construtor precisa ser igual ao nome da classe;
2. Não deve ter tipo de retorno;
3. Podemos escrever vários construtores para mesma classe.

Esta sintaxe pode ser vista na Figura 32 e um exemplo dessa declaração na Figura
33.

Figura 32. Representação da sintaxe de um construtor. Elaborado pelo autor.

Figura 33. Exemplo de sintaxe de um construtor na classe Mamifero. Elaborado pelo autor.

2.2. Chamando Outro Construtor

Um construtor só poderá ser executado durante a construção do objeto, depois


disso, você não conseguirá chamar o construtor em um objeto já tenha sido construído.
Porém, para você não ter que ficar copiando e colando, você poderá fazer um construtor
chamar outro construtor, durante a construção de um objeto. Essa técnica é apresentada
por Silveira (2006) e poderá ser vista na Figura 34.

UNIDADE II Trabalhando com os Métodos e suas Referências 48


Figura 34. Exemplo de chamada de outro construtor. Elaborado pelo autor.

Ainda seguindo a técnica de Silveira (2006), existe outro motivo para a utilização
desta técnica, a facilidade para sua implementação. Poderemos criar um construtor que
receberá diversos argumentos para que o usuário de uma classe não seja obrigado a
chamar diversos métodos do tipo set().

Quando implementamos uma classe com todos os seus atributos privados, seus
métodos getters() e setters() e um construtor default (vazio), na verdade nós estaremos
criando um Java Bean, que não deverá ser confundido com o EJB, que é Enterprise Java
Beans. Para saber mais acesse: http://java.sun.com/products/javabeans/

UNIDADE II Trabalhando com os Métodos e suas Referências 49


3. VISÃO GERAL DOS OPERADORES

Dentro de um método, a execução prosseguirá na sequência em que as instruções


ocorrerem. Em outras palavras, a execução se dará, a partir do cabeçalho do método para
a próxima, de cima para baixo. No entanto, as regras de negócios nos exibem alterar esse
fluxo para contemplar condições diferentes. Essas situações são extremamente comuns
em programação. Por exemplo: um site poderá pedir uma senha e seu código não deverá
dar acesso a ele, se a senha for inválida. Logo, o código que dará acesso não deverá ser
executado, se uma senha inválida for inserida. Se uma senha inválida for inserida, você
poderá dar ao usuário mais duas (e somente duas) oportunidades de inseri-la corretamente.
Para tratar situações em que o fluxo de execução do programa deverá ser alterado, Java
fornecerá um amplo conjunto de estruturas condicionais, de exceção e repetição.

3.1. Estruturas Condicionais

Schildt (2013) trata sobre as estruturas condicionais existem em todas as linguagens


de programação e descreve como elas possibilitam que a execução de um programa, seja
desviada de acordo com certas condições. Os comandos condicionais ou ainda instruções
condicionais, usados em Java, são if-else e switch-case. Essas duas estruturas de desvio
existentes na linguagem possibilitam executar diferentes trechos de um programa com
base em certas condições.

UNIDADE II Trabalhando com os Métodos e suas Referências 50


3.1.1. A Estrutura if-else

Schildt (2013) ainda trata sobre o if, em conjunto com o else, formando uma
estrutura que permite a seleção entre dois caminhos distintos para execução, dependendo
do resultado (verdadeiro ou falso) de uma expressão lógica (condição). Nesse tipo de
estrutura, se a condição for verdadeira, serão executadas as instruções que estiverem
posicionadas entre as instruções if/else. Sendo a condição falsa, serão executadas as
instruções que estiverem após a instrução else. A sintaxe para a utilização do conjunto if
else será demonstrada em seguida. Observe, na Figura 35, que a condição sempre deverá
aparecer entre parênteses, item obrigatório na linguagem Java.

Figura 35. Exemplo de sintaxe para a utilização do conjunto if else. Elaborado pelo autor.

A Figura 36 traz uma representação gráfica para ajudá-lo  a entender o funcionamento


dessa estrutura. Cada losango poderá ser considerado uma instrução if que contém uma
expressão lógica (condição). Veja que dependendo do resultado da condição (verdadeira
ou falsa) será executado um bloco diferente (1 ou 2) de instruções. É importante entender
também que toda estrutura if possui um início e um final, nos quais os dois caminhos se
encerram.

Figura 36. Representação gráfica da instrução if else.(FURGERI, 2015, p.43).

UNIDADE II Trabalhando com os Métodos e suas Referências 51


“Assim como a maioria das instruções em Java, o conjunto if-else deverá ser
utilizado com minúsculas e, caso haja apenas uma instrução a ser executada,
tanto no if como no else, o uso das chaves será desnecessário. Lembre-se
de que as chaves serão utilizadas quando um bloco de instruções precisa ser
executado, isto é, mais do que uma instrução. A estrutura if-else apresentada
não é a única válida, pois existem outras maneiras diferentes de se criar essa
estrutura: if sem o else, if com o else e if com o else aninhado.” (FURGERI,
2015, p.43).

Compare as representações gráficas dessas variações nas Figuras 37, 38 e 39.

Figura 37. Representação gráfica da instrução if sem else. (FURGERI, 2015, p.43).

Figura 38. Representação gráfica da instrução if com else. (FURGERI, 2015, p.44).

UNIDADE II Trabalhando com os Métodos e suas Referências 52


Figura 39. Representação gráfica da instrução if com else aninhado. (FURGERI, 2015, 44).

No primeiro caso é executado um bloco de instruções somente se a condição for


verdadeira; no segundo caso será executado um bloco de instruções para a condição
verdadeira e outro para a falsa. Já no terceiro caso, quando encontrada a primeira condição
verdadeira todas as outras serão desconsideradas. Seja o caminho que for apenas um
bloco de instruções será executado. O terceiro caso demonstra que para cada condição
falsa, será executada outra condição, mas poderia ser representado ao contrário, ou seja,
a condição verdadeira poderia levar à execução de outra condição.

3.1.2. Estrutura 1: if Sem else

O Exemplo apresentado na Figura 40, mostra um uso prático do if sem a presença


do else. Trata-se de uma classe em que o usuário seleciona uma opção (Masculino ou
Feminino) e a partir disso será usada a instrução if para executar instruções diferentes.

UNIDADE II Trabalhando com os Métodos e suas Referências 53


Figura 40. Exemplo da listagem da classe if. Elaborado pelo autor.

Figura 41. Tela de execução da Figura 40 com seleção de Feminino. (FURGERI, 2015, 46).

O Exemplo da Figura 42, mostra um uso prático do if-else para validar a entrada do
usuário. Serão realizadas três validações: em primeiro lugar, verifica se o usuário realmente
entrou com um valor na caixa de diálogo, depois verifica se o valor digitado é numérico, logo
a seguir verifica se esse valor está entre 1 e 12 (a faixa de valores possíveis, uma vez que
um mês deverá assumir apenas valores entre 1 e 12).

Figura 42. Listagem da classe IfComElse. Elaborado pelo autor.

UNIDADE II Trabalhando com os Métodos e suas Referências 54


Figura 43. Tela de execução da Figura 42 com seleção do mês 5. (FURGERI, 2015, 47).

O Exemplo 44, mostra como é possível criar uma estrutura em que cada instrução
else realiza a abertura de um novo if. Ao analisar essa estrutura, podemos notar que existe
um (ou mais) if dentro de um else.

Figura 44. Listagem da classe IfComElseAninhado. Elaborado pelo autor.

3.1.3. Estrutura switch-case

“A estrutura switch-case se refere à outra modalidade de desvio da execução do


programa de acordo com certas condições, semelhante ao uso da instrução if. Ao trabalhar
com uma grande quantidade de desvios condicionais contendo instruções if, pode-se
comprometer a inteligibilidade do programa, dificultando sua interpretação. A estrutura
switch-case possibilita uma forma mais adequada e eficiente de atender a esse tipo de
situação, constituindo-se uma estrutura de controle com múltipla escolha.” (FURGERI,
2015, 48).

UNIDADE II Trabalhando com os Métodos e suas Referências 55


A estrutura switch-case equivale a um conjunto de instruções if encadeadas,
fornecendo maior inteligibilidade. Sua sintaxe é a apresentada na Figura 45.

Figura 45. Exemplo de sintaxe da estrutura switch-case. Elaborado pelo autor.

Na primeira linha do switch é avaliado o resultado da expressão, que é comparado


nas diretivas case, executando o bloco de instruções quando a expressão coincidir com
o valor colocado ao lado direito do case. Em outras palavras, supondo que o valor da
expressão seja igual a 2, serão executadas as instruções localizadas entre case 2: e break.
A cada case o programa compara o valor da expressão com o valor colocado no case. Caso
os valores sejam iguais, todas as instruções serão executadas até que se encontre uma
instrução break, que encerra o switch e faz a execução do programa desviar para o ponto
após a chave de encerramento do switch. O programa percorre todas as diretivas case
até que uma delas seja igual à expressão inserida no switch. Caso nenhuma diretiva case
possua o valor correspondente da expressão, serão executadas as instruções localizadas
na diretiva default que será opcional. Veja a representação gráfica da estrutura do switch-
case na Figura 46.

Figura 46. Representação gráfica da estrutura switch-case. (FURGERI, 2015, p.49).

UNIDADE II Trabalhando com os Métodos e suas Referências 56


O Exemplo da Figura 47, demonstra de forma clara a utilização da estrutura switch-
case, simulando os meses do ano, em que o usuário entra com um número e o programa
retorna o mês correspondente por extenso.

Figura 47. Listagem da classe SwitchCase. Elaborado pelo autor.

Figura 48. Tela de execução da Figura 47 com seleção do mês 2. (FURGERI, 2015, p.50).

UNIDADE II Trabalhando com os Métodos e suas Referências 57


4. INSTRUÇÕES DE REPETIÇÕES

“Os laços de repetição (looping) formam uma importante estrutura nas lin-
guagens de programação por possibilitarem a repetição da execução de um
bloco de instruções em um programa. Eles determinam que um certo bloco
seja executado repetidamente até que uma condição específica ocorra. A re-
petição é uma das estruturas mais usadas em programação, possibilitando a
criação de contadores, temporizado- res, rotinas para classificação, obtenção
e recuperação de dados. A criação de laços de repetição em Java é feita a
partir das estruturas for, while e do-while” (FURGERI, 2015, p.56).

4.1. Instrução De Repetição While

Tucker (2009) trata uma instrução de repetição como uma especificação que um
programa deverá repetir uma ação enquanto alguma condição permanecer verdadeira.
A instrução de pseudocódigo descreve a repetição durante uma viagem de compras. A
condição “enquanto houver mais itens em minha lista de compras” poderá ser verdadeira ou
falsa. Se ela for verdadeira, então a ação “Compre o próximo item e risque-o de minha lista”
será realizada. Essa ação será realizada repetidamente, enquanto a condição permanecer
verdadeira.

A(s) instrução (ões) contida(s) na trecho de código de repetição While constitui


(em) seu corpo, que poderá ser uma instrução única ou um bloco. Por fim, a condição se
tornará falsa, quando o último item da lista de compras tiver sido comprado e removido.
Neste ponto, a repetição termina e a primeira instrução depois da instrução de repetição
será executada, conforme trata Deitel (2013).

UNIDADE II Trabalhando com os Métodos e suas Referências 58


Figura 49. Sintaxe da instrução de repetição While. Elaborado pelo autor.

● Condição: poderá ser qualquer expressão ou valor que resulte em um verdadeiro


ou falso.
● O laço while será executado enquanto a condição for verdadeira. Quando esta se
tornar falsa o programa continua no próximo comando após o while.
● Para instrução de repetição while, o teste da condição de controle será feito no início
do laço, o que significa que se já for falsa os comandos dentro do laço não serão
executados.

Tucker (2009) ainda detalha a instrução while, apresentada na Figura 49, avaliando
o resultado da expressão (condição) antes de executar as instruções do bloco { }. Assim,
será possível que as instruções nunca sejam executadas, caso a condição seja inicialmente
falsa. Um problema típico, relacionado à avaliação da condição while, é o laço infinito. Caso
a condição nunca se torne falsa, o laço será repetido infinitamente. Um exemplo do laço
While está presente na Figura 50.

Figura 50. Exemplo da instrução de repetição while na classe WhileDemo.


Elaborado pelo autor.

Há outro tipo de laço condicional, o chamado do-while, que é bem parecido com
o while, porém o conjunto de instruções será executado antes da avaliação da expressão
lógica. Isso faz com que essas instruções sejam executadas pelo menos uma vez, conforme
apresenta Furgeri (2015). Veja como a sintaxe do do-while é bem parecida com a do while

UNIDADE II Trabalhando com os Métodos e suas Referências 59


na Figura 51.

Figura 51. Sintaxe da instrução de repetição do-while. Elaborado pelo autor.

Embora as chaves não sejam necessárias quando houver apenas uma instrução
presente, elas serão usadas com frequência para melhorar a legibilidade da estrutura do-
while, evitando, assim, confusão com while. O laço do-while será executado enquanto a
expressão condicional for verdadeira. O programa apresentado na Figura 52 demonstra o
uso do do-while ficando em laço até você adivinhar a letra.

4.2. Instrução De Repetição For

Ainda temos Knudsen (2005) tratando sobre a instrução for como um tipo de contador
finito, isto é, ela realiza a contagem de um valor inicial conhecido até um valor final também
conhecido. Uma possível representação gráfica da estrutura de funcionamento de um laço
de repetição for poderá ser visualizada na Figura 53. No início da execução da estrutura
será inicializada uma variável. Após isto, o valor dessa variável será verificado na condição,
na representação gráfica do losango, e enquanto essa condição for verdadeira o bloco
de instruções será executado dentro da estrutura. Somente quando a condição se tornar
falsa é que a execução será desviada para o final da estrutura do laço. O incremento ou
decremento do valor da variável será essencial para que o laço tenha uma saída (encerre),
caso contrário, a execução nunca sairá do laço.

UNIDADE II Trabalhando com os Métodos e suas Referências 60


Figura 52. Exemplo da instrução de repetição do-while, na classe Adivinhar4.
Elaborado pelo autor.

A Figura 54 examina mais detalhadamente a instrução for. O cabeçalho de for é o


“faz tudo”, ele especificará cada item necessário para repetição controlada por contador,
com uma variável de controle. Se houver mais de uma instrução no corpo do for, as chaves
({ e }) serão exigidas para definir o corpo do loop.

UNIDADE II Trabalhando com os Métodos e suas Referências 61


Figura 53. Representação gráfica da instrução for. (FURGERI, 2015, p.57).

Figura 54. Componentes de cabeçalho de instrução for.(DEITEL, 2017, p.122).

O formato geral da instrução for é apresentada na Figura 55.

Figura 55. Sintaxe da instrução de repetição for. Elaborado pelo autor.

Segundo Deitel (2017, p. 123):


“a expressão inicialização nomeará a variável de controle do loop e opcio-
nalmente fornecerá seu valor inicial, condiçãoDeContinuaçãoDoLoop será a
condição que determinará se o loop deverá continuar executando e o incre-
mento modificará o valor da variável de controle, para que a condição de
continuação do loop, por fim se torne falsa. Os dois pontos e vírgulas no
cabeçalho for serão necessários. Se a condição de continuação do loop for
inicialmente false, o programa não executará o corpo da instrução for. Em vez
disso, a execução prosseguirá com a instrução seguinte ao for.”

A instrução for muitas vezes poderá ser representada com uma while equivalente
da maneira descrita na Figura 56.

Figura 56. Sintaxe da instrução de repetição for representada por while. Elaborado pelo autor.

UNIDADE II Trabalhando com os Métodos e suas Referências 62


Figura 57. Exemplo da instrução de repetição for na simulação de um relógio. Elaborado pelo autor.

Funcionalidades comentadas no exemplo da Figura 57:

• Linhas 5 a 7: contém os laços de repetição para o controle das horas (0 a


23), minutos (0 a 59) e segundos (0 a 59). Um ponto a ser observado será a
possibilidade de criação de um laço de repetição dentro do outro. Quando isso
ocorre, o laço interno é executado n vezes, de acordo com o número de vezes
definido pelo laço superior. Como exemplo, observe as linhas 7 a 18. O laço
mais interno (s) controla os segundos e é executado 60 vezes a cada minuto (o
laço superior). Da mesma forma, o laço dos minutos será executado 60 vezes a
cada hora (o laço superior).
• Linha 10: contém Thread.sleep (1000); que invoca um temporizador que espera
mil milissegundos (um segundo) até a execução da próxima instrução. Esse
procedimento poderá gerar uma exceção e por isso deverá ser usado dentro de
um bloco try, ou poderá ser desconsiderado caso você prefira usar a cláusula
throws. No último caso, o exemplo ficaria um pouco mais resumido: deveria ser
adicionado “throws InterruptedException” ao final da linha 3 e retiradas as linhas
9 e 13 a 16. O uso de Thread talvez não seja a melhor forma de se criar uma
temporização; para isso existem outras classes como Timer e TimerTask, cujo
estudo foge aos objetivos. Também não é objetivo estudar threads. Além disso,
o uso do método sleep dentro de um laço de repetição não é muito recomendado
por questões de desempenho.

UNIDADE II Trabalhando com os Métodos e suas Referências 63


• Linhas 11 e 12: controlam o final da execução do relógio. Quando o relógio
contar dez segundos, o programa será encerrado por meio de System.exit (0).
Sempre que for necessário forçar o encerramento de um programa, o método
exit poderá ser usado. Se você estiver usando uma IDE (NetBeans, Eclipse)
existe um botão específico para isso, um botão de stop, normalmente um
quadradinho vermelho. Os resultados obtidos ao executar o exemplo da Figura
57 poderão ser vistos na Figura 58.

Figura 58. Saída do código apresentado no exemplo da Figura 57. Elaborado pelo autor.

UNIDADE II Trabalhando com os Métodos e suas Referências 64


SAIBA MAIS
Os 4 pilares da Programação Orientada a Objetos

Caro (a) aluno (a), com a finalidade de ampliar o conhecimento voltado à programação
orientada a objetos, ofereço a você como sugestão para leitura este artigo que trata dos
quatro pilares da programação orientada a objetos, que são a abstração, encapsulamen-
to, herança e o polimorfismo. Estas são as bases da programação orientada a objetos,
quando se tem a perfeita compreensão sobre elas, você poderá ter um desenvolvimento
de software melhor e com maior facilidade na hora de programar.

“O desenvolvimento de software é extremamente amplo. Nesse mercado, existem


diversas linguagens de programação, que seguem diferentes paradigmas. Um desses
paradigmas é a Orientação a Objetos, que atualmente é o mais difundido entre todos.
Isso acontece porque se trata de um padrão que tem evoluído muito, principalmente
em questões voltadas para segurança e reaproveitamento de código, o que é muito
importante no desenvolvimento de qualquer aplicação moderna»...

Link do site:
https://www.devmedia.com.br/os-4-pilares-da-programacao-orientada-a-objetos/9264

REFLITA
“Algumas pessoas acham que foco significa dizer sim para a coisa em que você vai se
focar. Mas não é nada disso. Significa dizer não às centenas de outras boas ideias que
existem. Você precisa selecionar cuidadosamente.” (Steve Jobs).

Inspirado em uma das maiores mentes da computação, Steve Jobs, hoje é o dia certo
para estudar, trabalhar, buscar algo novo. Mas, não devemos fazer isso tentando abra-
çar o mundo, ou seja, tentando fazer tudo ao mesmo tempo, mas sim, um de cada vez,
porém de forma completa e totalmente envolvida. Assim, priorizar será a competência
que você deverá aprimorar, somente assim será capaz de ir além e fazer coisas que
outros não podem.
Hoje é o dia!
Faça o hoje valer a pena, fazendo boas escolhas!

Referência:
https://www.tecmundo.com.br/internet/3145-frases-impactantes-sobre-tecnologia-e-in-
formatica.htm

UNIDADE II Trabalhando com os Métodos e suas Referências 65


CONSIDERAÇÕES FINAIS

Caro(a) aluno(a) que bom que chegou até aqui!


Nosso objetivo foi apresentar-lhes os conceitos e exemplos para facilitar o
entendimento de uma das linguagens mais usadas na programação na atualidade, a
Programação Orientada a Objetos.
Com uma rápida introdução aos conceitos e suas aplicações, você pôde ver uma
introdução direcionada ao uso da palavra reservada this.
Você pôde constatar as suas principais características e usabilidades, estudando
os conceitos sobre os construtores. Você pôde ver também que o método construtor é
o responsável por alocar espaço na memória para a manipulação do objeto e conter a
chamada para outros métodos.
Com a utilização de estudos dirigidos, você pôde estudar e analisar os operadores
e suas estruturas.  Você viu que para tratar situações em que, o fluxo de execução do
programa, quando precisar ser alterado, Java fornecerá um amplo conjunto de estruturas
condicionais, de exceção e repetição. Foi apresentado também, as estruturas condicionais
usadas em Java, que são if-else e switch-case.
Outro ponto importante nessa unidade foram os conceitos a respeito das instruções
de repetições também chamados de looping formam uma importante estrutura nas linguagens
de programação, repetindo a execução de um bloco de instruções em um programa.
Neste livro a Programação Orientada a Objetos, vem acompanhada de exemplos na
linguagem de Programação Java. Recomendamos que você aprofunde seus conhecimentos
dessa linguagem através das dicas de leituras complementares, pois a prática conduz ao
aperfeiçoamento. Portanto estude e pratique constantemente! Somente com dedicação aos
estudos e as práticas, você se tornará um excelente profissional.
Um grande abraço!
Te espero na próxima unidade.
Até lá!

UNIDADE II Trabalhando com os Métodos e suas Referências 66


MATERIAL COMPLEMENTAR

LIVRO
Título: Estruturas de Dados & Algoritmos em Java
Autor: Michael T. Goodrich, Roberto Tamassia.
Editora: Bookman | ARTMED Editora.
Sinopse: Este livro oferece uma introdução a estruturas de dados
e algoritmos, incluindo projeto, análise e implementação. Em
um texto simples e claro, os autores utilizam recursos visuais e
cenários do mundo real, focando as funções mais populares na
análise de algoritmos.

FILME/VÍDEO
Título: Os pilares da Programação Orientada a Objetos.
Ano: 2018.
Sinopse: A Orientação a Objetos é um dos paradigmas de análise
e desenvolvimento de softwares mais utilizados na atualidade.
Ele se baseia na representação dos elementos do mundo real e
nas interações entre eles, que se refletem no projeto na forma de
classes e métodos. Para que isso seja possível esse paradigma
conta com quatro pilares que serão explicados neste DevCast:
abstração, herança, polimorfismo e encapsulamento.
Link do vídeo: https://www.devmedia.com.br/os-pilares-da-
programacao-orientada-a-objetos/38384

UNIDADE II Trabalhando com os Métodos e suas Referências 67


UNIDADE III
Pilares da Orientação a
Objetos e seus Comandos
Professor Mestre Ricardo Vieira

Plano de Estudo:

1. INTRODUÇÃO AOS COMANDOS DE UMA LINGUAGEM ORIENTADA A OBJETOS


2. CONCEITOS AVANÇADOS SOBRE CLASSES
3. CONSTRUTORES
4. HERANÇA
5. POLIMORFISMO
6. CONSIDERAÇÕES FINAIS
7. REFERÊNCIAS

Objetivos de Aprendizagem:

● Conceituar e contextualizar os comandos de uma linguagem orientada a objetos.


● Estabelecer a importância dos conceitos avançados sobre as classes.  
● Compreender os tipos de construtores da programação orientada a objetos.
● Conceituar e contextualizar a respeito de herança e polimorfismo.

68
INTRODUÇÃO

Esta unidade inicia os estudos com uma breve introdução ao conceito e a utilização
dos comandos de uma linguagem orientada a objetos. Você verá nesta unidade que a API
String torna a codificação de caracteres transparente para você. O Unicode também é
compatível com ASCII. Você poderá se aprofundar no conceito sobre o sistema de tipos de
uma linguagem de programação, descrevendo como seus elementos de dados (variáveis e
constantes) estão associados ao armazenamento real.

Com o estudo mais aprofundado e específico sobre os conceitos avançados sobre


classes e seus modificadores de acesso a classes e seus membros. Você verá que uma
Classe é um código que descreve um tipo específico de objeto. Ele especifica os dados que
um objeto poderá conter (os campos de objetos) e as ações que um objeto poderá executar
(os métodos do objeto).

E verá também que os modificadores de acesso são padrões de visibilidade de


acessos às classes, atributos e métodos. Estes modificadores são palavras-chaves
reservadas pela linguagem Java, ou seja, palavras reservadas não podem ser usadas
como nome de métodos, classes ou atributos.

Veremos também uma abordagem mais aprofundada a respeito dos construtores e


verá que será possível declarar seu próprio construtor a fim de especificar como objetos de
uma classe devem ser inicializados.

Além disso, trataremos sobre herança detalhando sua generalização e


especialização. A linguagem de programação Java dá suporte à herança permitindo que
uma classe incorpore outra classe em sua declaração. Com a utilização da palavra-chave
extends, e muito mais.
Então vamos aos estudos! Tenha um bom aprendizado...

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 69


1. INTRODUÇÃO AOS COMANDOS DE UMA LINGUAGEM ORIENTADA A OBJETOS

Conforme descreve Kalinovsky (2004), Java é uma linguagem para a Internet.


Como as pessoas da Net falam e escrevem em muitas línguas humanas diferentes, Java
também deverá ser capaz de lidar com um grande número de idiomas.

Uma das maneiras pelas quais o Java suporta acesso internacional é através da
codificação de caracteres Unicode. Unicode usa uma codificação de caracteres de 16
bits. É um padrão mundial que suporta os scripts (conjuntos de caracteres) da maioria dos
idiomas.

1.1. Codificação De Texto

Ainda segundo Kalinovsky (2004), o código-fonte Java pode ser escrito usando a
codificação de caracteres Unicode e armazenado em seu formato completo de 16 bits ou
com valores de caracteres Unicode codificados em ASCII. Isso torna o Java uma linguagem
amigável para programadores que não falam inglês, que podem usar seu alfabeto nativo
para nomes de classes, métodos e variáveis, ​​no código Java. O tipo char de Java e os
objetos String também suportam Unicode.

Mas se você está preocupado em ter que trabalhar com caracteres de dois bytes,
pode relaxar. A API String torna a codificação de caracteres transparente para você. O

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 70


Unicode também é compatível com ASCII; os primeiros 256 caracteres serão definidos
como idênticos aos primeiros 256 caracteres da codificação ISO8859-1 (Latin-1); Se você
ficar com esses valores, realmente não haverá distinção entre os dois.

A maioria das plataformas não pode exibir todos os caracteres Unicode, atualmente
definido. Como resultado, os programas Java podem ser gravados com sequências de
escape Unicode especiais. Um caractere Unicode pode ser representado com essa
sequência de escape:
\ uxxxx

xxxx é uma sequência de um a quatro dígitos hexadecimais. A sequência de escape


indica um caractere Unicode codificado em ASCII. Essa também é a forma que o Java usa
para produzir um caractere Unicode em um ambiente que não os suporta.

Java armazena e manipula caracteres e strings internamente como valores Unicode.


O Java também vem com classes para ler e gravar fluxos de caracteres formatados em
Unicode.

1.2. Comentários

Conforme trata Knudsen(2005), Java suporta ambos os comentários de bloco no


estilo C delimitados por / * e * / e comentários de linha no estilo C ++ indicados por // e
apresentados na Figura 59.

Figura 59. Exemplo de comentários em bloco e em linha única. Elaborado pelo autor.

Como em C, os comentários de bloco não podem ser aninhados. Comentários de


linha única são delimitados pelo final de uma linha; extra // indicadores dentro de uma única

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 71


linha não têm efeito. Comentários de linha são úteis para comentários curtos dentro de
métodos; eles não entram em conflito com os indicadores de bloqueio de bloco em torno de
grandes blocos de código durante o desenvolvimento.

1.3. Comentários Javadoc

Conforme trata ainda Knudsen(2005), e por convenção, um comentário de bloco


começando com /** indica um comentário de documento especial. Um comentário doc
foi projetado para ser extraído por geradores automatizados de documentação, como o
programa javadoc da DSK. Um comentário de doc é terminado pelo próximo * /, assim como
com um comentário de bloco regular. O espaçamento principal até um * em cada linha será
ignorado; as linhas que começarem com @ são interpretadas como tags especiais para o
gerador de documentação. Na Figura 60 temos um exemplo.

Figura 60. Exemplo de comentários javadoc. Elaborado pelo autor.

O javadoc cria documentação em formato HTML das classes lendo o código-fonte


e os comentários incorporados. As informações do autor e da versão são apresentadas na
saída, e as tags @see fazem links de hipertexto para a documentação de classe apropriada.
O compilador também analisa os comentários do doc; Em particular, ele está interessado
na tag @deprecated, o que significa que o método foi declarado obsoleto e deve ser evitado
em novos programas. O compilador gera uma mensagem de aviso sempre que ele vê o uso
de um recurso reprovado em seu código.

Os comentários do documento poderão aparecer acima das definições de classe,


método e variável, mas algumas tags poderão não ser aplicáveis ​​a todas elas. Por exemplo,
uma declaração de variável poderá conter apenas uma tag @see. A Tabela 03 resume as
tags usadas nos comentários do documento.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 72


Tabela 03. Padrão de tags para comentários de documento. Elaborado pelo autor.

1.4. Tipos

Goodrich(2013) trata sobre o sistema de tipos de uma linguagem de programação


e descreve que seus elementos de dados (variáveis e
​​ constantes) estarão associados ao
armazenamento real. Em uma linguagem com tipagem estática, como C ou C ++, o tipo de
um elemento de dados será um atributo simples e imutável que geralmente corresponde
diretamente a algum fenômeno de hardware subjacente, como um valor de registro ou uma
indeterminação de ponteiro. Em uma linguagem mais dinâmica, como Smalltalk ou Lisp, as
variáveis ​​podem ser atribuídas a elementos arbitrários e poderão efetivamente mudar seu
tipo ao longo de sua vida útil. Uma quantidade considerável de sobrecarga vai para validar
o que acontece nessas linguagens em tempo de execução. Linguagens de script como Perl
e Tcl alcançam facilidade de uso, fornecendo sistemas de tipos simplificados drasticamente
nos quais apenas determinados elementos de dados podem ser armazenados em variáveis,
e os valores são unificados em uma representação comum, como strings.

conforme Goodrich(2013) descreve, Java combina os melhores recursos de


linguagens tipadas e dinamicamente tipadas. Como em uma linguagem tipada estaticamente,
toda variável e elemento de programação em Java tem um tipo que será conhecido em tempo
de compilação, então o sistema, em tempo de execução, normalmente não precisa verificar
a validade de tipo das atribuições enquanto o código está sendo executado. Diferentemente
de C ou C ++, no entanto, Java também mantém informações de tempo de execução sobre
objetos e usa isso para permitir polimorfismo verdadeiramente seguro e conversão, usando
um objeto como um tipo diferente de seu tipo declarado.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 73


Os tipos de dados Java se enquadram em duas categorias. Tipos primitivos que
representam valores simples que possuem funcionalidade integrada na linguagem. Eles
são elementos fixos, como constantes literais e números. Tipos de referência (ou tipos de
classes) que incluem objetos e matrizes. Eles são chamados de tipos de referência porque
são passados ​​“por referência”.

1.4.1. Tipos Primitivos

Segundo Jacobi(2006), os números, caracteres e valores booleanos são elementos


fundamentais em Java. Ao contrário de outras linguagens orientadas a objetos (talvez mais
puras), elas não são objetos. Para as situações em que é desejável tratar um valor primitivo
como um objeto, o Java fornece classes “wrapper”. Uma grande vantagem do tratamento
de valores primitivos é que o compilador Java pode otimizar mais prontamente seu uso.

Outro importante recurso de portabilidade do Java é que tipos primitivos são


definidos com precisão. Por exemplo, você nunca precisa se preocupar com o tamanho
de um int em uma plataforma específica; é sempre um número de complemento de dois,
assinado de 32 bits. A Tabela 04 apresenta os tipos primitivos do Java.

Tabela 04. Exemplos de tipos de dados primitivos. Elaborado pelo autor.

Ainda conforme Jacobi(2006), em C, você pode criar um tipo de dados novo e


complexo criando uma estrutura. Em Java (e outras linguagens orientadas a objetos), você
cria uma classe que define um novo tipo no idioma. Por exemplo, se criarmos uma nova
classe chamada Foo em Java, também estaremos criando implicitamente um novo tipo
chamado Foo. O tipo de um item determina como ele é usado e onde é atribuído. Um item
do tipo Foo pode, em geral, ser atribuído a uma variável do tipo Foo ou passado como um

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 74


argumento para um método que aceita um valor de Foo.

Em uma linguagem orientada a objetos, como Java, um tipo não é necessariamente


apenas um atributo simples. Os tipos de referência estão relacionados da mesma maneira
que as classes que eles representam. As classes existem em uma hierarquia, onde uma
subclasse é um tipo especializado de sua classe pai. Os tipos correspondentes terão o
mesmo relacionamento, em que o tipo da classe filha é considerado um subtipo da classe
pai. Como as classes filha sempre estendem seus pais e tem, no mínimo, a mesma
funcionalidade, um objeto do tipo da criança pode ser usado no lugar de um objeto do tipo
pai. Por exemplo, se eu criar uma nova classe, Bar, que estenda Foo, haverá uma nova Bar
de tipos que é considerada um subtipo de Foo. Objetos do tipo Bar podem então ser usados​​
em qualquer lugar em que um objeto do tipo Foo possa ser usado; um objeto do tipo Bar é
dito ser atribuído a uma variável do tipo Foo. Isso é chamado de polimorfismo de subtipo e
é um dos principais recursos de uma linguagem orientada a objetos. Examinaremos mais
de perto as classes e objetos nesta unidade.

Jacobi(2006) também trata sobre os tipos de referência e como eles sempre


apontam para objetos, e os objetos são sempre definidos por classes. No entanto, dois
tipos especiais de tipos de referência especificam o tipo de objeto para o qual apontam
de maneira ligeiramente diferente. Arrays em Java têm um lugar especial no sistema de
tipos. Eles são um tipo especial de objeto criado automaticamente para conter um outro
tipo de objeto, conhecido como o tipo base. Declarar uma referência de tipo de array cria
implicitamente o novo tipo de classe.

Jacobi(2006) descreve as Interfaces como sendo um pouco mais “sorrateiras”.


Uma interface define um conjunto de métodos e um tipo correspondente. Qualquer objeto
que implemente todos os métodos da interface pode ser tratado como um objeto desse
tipo. Variáveis ​​e argumentos de método podem ser declarados como sendo de tipos de
interface, assim como tipos de classes, e qualquer objeto que implemente a interface pode
ser atribuído a eles. Isso permite que o Java cruze as linhas da hierarquia de classes de
uma maneira segura para o tipo.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 75


2. CONCEITOS AVANÇADOS SOBRE CLASSES

Schildt(2013) trata uma classe como um código que descreve um tipo específico
de objeto. Ele especificará os dados que um objeto poderá conter (os campos de objetos) e
as ações que um objeto poderá executar (os métodos do objeto). Você poderá pensar em
uma classe como um projeto de código que poderá ser usado para criar um tipo específico
de objeto. Ela serve a um propósito semelhante ao do projeto de uma casa.

O projeto em si não é uma casa, mas uma descrição detalhada de uma casa. Quando
usamos o projeto para construir uma casa real, poderíamos dizer que estamos construindo
uma instância da casa descrita pelo projeto. Se assim o desejarmos, poderemos construir
várias casas idênticas a partir do mesmo projeto. Cada casa é uma instância separada da
casa descrita pelo projeto. Exemplo este apresentado na Figura 61.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 76


Figura 61. Planta que descreve uma casa, instâncias da casa descritas pelo projeto.
Fonte: Dcore Você (2018)

Então, uma classe não é um objeto, mas uma descrição de um objeto. Quando um
programa está em execução, ele pode usar a classe para criar, na memória, tantos objetos
de um tipo específico quanto necessário. Cada bate-papo de objeto é criado a partir de uma
classe é chamado de instância da classe.

2.1. Objetos

Ainda conforme Schildt(2013), um objeto é um componente de software que existe


na memória e serve a um propósito específico em um programa. Um objeto será criado a
partir de uma classe que contenha um código descrevendo o objeto.

Se você já dirigiu um carro, sabe que um carro é composto por muitos componentes.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 77


Ele tem um volante, um pedal de acelerador, um pedal de freio, um câmbio, um velocímetro
e vários outros dispositivos com os quais os motoristas interagem. Há também muitos
componentes sob o capô, como o motor, a bateria, o radiador e assim por diante. Então,
um carro não é apenas um único objeto, mas sim uma coleção de objetos que funcionam
juntos. Essa mesma noção se aplica também à programação de computadores. A maioria
das linguagens de programação atualmente em uso é orientada a objetos.

Com uma linguagem orientada a objetos, como o Java, você poderá criar programas
que transmitem a programação. No entanto, em um dispositivo IMM (Integrated Management
Module - Módulo de Gerenciamento Integrado), como um volante ou um pedal de freio. É
um componente de software que existe na memória do computador e executa uma tarefa
específica. No software, um objeto tem dois recursos gerais:

1. Um objeto poderá armazenar dados. Os dados armazenados em um objeto


serão comumente chamados de campos.
2. Um objeto poderá realizar operações. As operações que um objeto poderá
executar são chamadas de métodos.

Objetos são muito importantes na linguagem de programação orientada a objetos


Java. Existem alguns exemplos de objetos sobre os quais você aprendeu anteriormente:

• Se precisar ler a entrada do teclado ou de um arquivo, use um objeto Scanner;


• Se você precisa gerar números aleatórios, você poderá usar um objeto Random;
• Se você precisar gravar a saída em um arquivo, poderá usar um objeto
PrintWriter.

Quando um programa precisa dos serviços de um determinado tipo de objeto, ele


criará esse objeto na memória e chamará os métodos deste objeto conforme for necessário.

2.2. Estrutura de uma classe na API Java

Até agora, os objetos que você usou em seus programas são criados a partir de
classes na API Java. Por exemplo, toda vez que você criar um objeto Scanner, você criará
uma instância de uma classe chamada Scanner, que está na API Java. Da mesma forma,
quando você cria um objeto Random, está criando uma instância de uma classe denominada
Random, que está na API Java. O mesmo é verdadeiro para o objeto do PrintWriter. Quando

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 78


você precisar gravar dados em um arquivo, você criará uma instância da classe PrintWriter,
que também está na API Java.

Observe a Listagem de código da Figura 62, um programa que usa todos esses
tipos de objetos.

Figura 62. Listagem de código da classe ObjectDemo.Java. Elaborado pelo autor.

Em poucas palavras, este programa grava um número especificado de números


aleatórios em um arquivo chamado numbers.txt. Quando o programa for executado, ele
pedirá ao usuário a quantidade de números aleatórios para escrever. Em seguida, ele
escreverá pistas de muitos números para o arquivo. Para fazer seu trabalho, ele criará três
objetos:

1. Na linha 18, ele está criando uma instância da classe Scanner e atribuindo o

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 79


endereço do objeto a uma variável chamada keyboard. O objeto será usado
para ler a entrada do teclado;
2. Na linha 21, ele está criando uma instância da classe Random e atribuindo o
endereço do objeto a uma variável chamada rand. O objeto será usado para
gerar números aleatórios;
3. Na linha 24, ele está criando uma instância da classe PrintWriter e atribuindo o
endereço do objeto a uma variável denominada outputFile. O objeto será usado
para gravar a saída no arquivo numbers.txt.

A Figura 63 ilustra os três objetos que o programa está criando. Conforme o


programa for executado, ele usará esses objetos para realizar determinadas tarefas. Por
exemplo:

• Na linha 28, o método nextlnt do objeto Scanner é chamado para ler a entrada
do usuário (que é a quantidade de números aleatórios a serem gerados). O
valor retornado do método será atribuído à variável maxNumbers;
• Na linha 35, o método nextlnt do objeto Random será chamado para obter um
inteiro aleatório. O valor retornado do método será atribuído à variável numérica;
• Na linha 38, o método println do objeto PrintWriter será chamado para gravar o
valor da variável numérica no arquivo;
• Na linha 41, o método close do objeto PrintWriter é chamado para fechar o
arquivo.

Este exemplo simples demonstra como a maioria dos programas funciona. Um


programa geralmente criará os vários objetos necessários para concluir seu trabalho. Cada
objeto possuirá um conjunto de métodos que poderão ser chamados, fazendo com que o
objeto execute uma operação. Quando o programa precisa de um objeto para fazer algo,
ele chama o método apropriado.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 80


Figura 63. Objetos criados pelo programa ObjectDemo. Elaborado pelo autor.

2.3. Modificadores de acesso de classes e membros

Conforme Tucker(2009), os modificadores de acesso são padrões de visibilidade


de acessos às classes, atributos e métodos. Estes modificadores são palavras-chaves
reservadas pela linguagem Java, ou seja, palavras reservadas não podem ser usadas como
nome de métodos, classes ou atributos. Como boas práticas da linguagem  de programação
orientada a objetos Java, na maioria das declarações de variáveis de instância, será definida
os seus atributos com a palavra-chave private, para garantir a segurança de alterações
acidentais, sendo somente acessíveis através dos métodos. Essa ação tem como efeito
ajudar no encapsulamento dos dados, preservando ainda mais a segurança e a aplicação
de programação orientada a objetos da linguagem.

Segundo DevMedia(2013), o grande objetivo que os modificadores de acesso


apresentam, são tornar as implementações mais adequadas a diversidade de seus
propósitos. Os modificadores de acesso possui uma característica geral, eles deverão ser
definidos sempre em palavras minúsculas. Dessa maneira, deverão ser apresentados assim:
public, private, protected, default, static, final, native, synchronized, volatile. O uso adequado
dos modificadores de acesso será importante para a definição de uma implementação,
com as especificações de projeto, de maneira coerente, determinando assim, como serão
os acessos às classes, métodos e as variáveis. Dessa maneira, poderão se concretizar
conceitos como, por exemplo, o encapsulamento e a herança da programação orientado
a objetos.
Por exemplo, quando um programa criar (instanciar) um objeto da classe Banco, a

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 81


variável senha será encapsulada (ocultada) no objeto onde poderá ser acessada apenas
por métodos da classe do objeto, os métodos getters() e setters(), que manipulam a variável
de instância. Vejamos nos próximos tópicos a explicação sobre cada um dos modificadores.

2.3.1. Modificador public

Uma declaração com o modificador public poderá ser acessada de qualquer lugar
e por qualquer entidade que possa visualizar a classe a que ela pertença.

2.3.2. Modificador private

Os membros da classe definidos como private não poderão ser acessados ou


usados por nenhuma outra classe. Esse modificador não se aplica às classes, somente para
seus métodos e atributos. Esses atributos e métodos também não poderão ser visualizados
pelas classes herdadas.

Figura 64. Exemplo de declaração dos modificadores private, public e default.


Elaborado pelo autor.

2.3.3. Modificador protected

O modificador protected torna o membro acessível às classes do mesmo pacote ou


através de herança, seus membros herdados não são acessíveis a outras classes fora do
pacote em que foram declarados.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 82


2.3.4. Modificador default

A classe e/ou seus membros serão acessíveis somente por classes do mesmo
pacote, na sua declaração não será definido nenhum tipo de modificador, sendo este
identificado pelo compilador.

Figura 65. Exemplo de declaração do modificador default. Elaborado pelo autor.

2.3.5. Modificador static

Tucker(2009) também trata sobre a criação de uma variável que poderá ser acessada
por todas as instâncias de objetos desta classe como uma variável comum, ou seja, a
variável criada será a mesma em todas as instâncias e quando seu conteúdo é modificado
numa das instâncias, a modificação ocorre em todas as demais. E nas declarações de
métodos ajudam no acesso direto à classe, portanto não é necessário instanciar um objeto
para acessar o método.

No exemplo da Figura 66, será gerada a saída da contagem de 4 valores (1,2,3,4),


se comentarmos a linha que tem a variável static e descomentar a linha que não tem o
modificador static, veremos que a saída, nas chamadas dentro da função main(), terá 4
mensagens com o mesmo valor (1,1,1,1).
Nas variáveis estáticas isso acontece porque todas as instâncias da mesma classe
compartilham a mesma cópia das variáveis estáticas, sendo inicializadas quando a classe
é carregada (instanciada).

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 83


Figura 66. Exemplo de declaração e utilização do modificador static. Elaborado pelo autor.

2.3.6. Modificador final

Tucker(2009) ainda trata sobre o modificador final e descreve que o mesmo confere
«terminalidade” ao processo de herança, isto é, uma classe ao receber o modificador final
representará que chegou ao nível máximo de especialização e não poderá mais ser
especializada. Um exemplo clássico de classe final é a java.lang.String. A classe String,
por se tratar de um tipo de dado, foi definida como uma classe final. Outro motivo para o
uso do modificador final  é a segurança, dado que quando a classe for identificada como
sendo a String, se trata da classe java.lang.String propriamente dita e não de uma possível
classe herdeira, a qual pode ter sofrido alterações e apresentar funcionalidades alteradas.

Por sua vez, quando aplicado aos métodos, o modificador final garante que este
não será sobrescrito, o que implica que o método declarado como final terá o seu protótipo
mantido tal qual foi definido e, quando for chamado por um dos objetos da classe (ou
de classes herdeiras), seu código é que será executado. Dessa forma, nenhuma classe
herdeira será capaz de sobrescrever um método definido como final.

Essa propriedade confere segurança ao código implementado, evitando a


programação de subclasses que poderiam ter o mesmo protótipo do método, mas com
implementações diferentes. Mais especificamente, imagine que estamos tratando de um
método que confere a autenticação de usuários do sistema. Se este método for sobrescrito
por um código malicioso em alguma classe herdeira, poderia ser criada uma quebra de
segurança na autenticação, conferindo acesso a usuários não autorizados.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 84


Outra vantagem é o desempenho de execução, dado que as chamadas aos
métodos final serão substituídas por suas definições, isto é, pelo código contido na definição
do método (técnica de inclusão de código inline). Neste caso, o compilador poderá substituir
a chamada a um método final pelo código (corpo) do método, evitando o desvio de fluxo em
sua execução. Portanto, se um método possuir uma especificação bem definida e não for
sofrer especializações/redefinições pelas classes herdeiras, é aconselhável que o mesmo
receba o modificador final por razões de segurança e desempenho.

Figura 67. Exemplo de declaração do modificador final. Elaborado pelo autor.

Na Figura 67 podemos ver um exemplo de utilização do modificador final. Na linha


1 é declarada a classe ClasseFinal com o uso do modificador final . Nas linhas 2, 3, 4 e 5
serão declarados os atributos finais de classe. Na linha 4 temos também a instanciação do
objeto botao. Logo, não poderá haver nenhuma outra instanciação desse objeto na classe.
Assim, qualquer instrução como botao = new JButton(“rotulo do botao”) será entendida pelo
compilador como um erro.

Os atributos finais que não foram inicializados em sua declaração devem ser
inicializados no método construtor, como descrito nas linhas 8, 9, 10, 14, 15 e 16. Neste

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 85


exemplo existem dois métodos construtores, nos quais deverão ser inicializados todos
os atributos ainda não inicializados. Isto se faz necessário dado que não é conhecido a
priori qual será o método construtor que será utilizado para a criação do objeto da classe.
Se houver qualquer tentativa de uma nova atribuição de valores (tipos primitivos) ou re-
instanciação (objetos ou vetores) de atributos finais em qualquer outra parte do código, é
gerado um erro de compilação.

Na linha 27 temos um exemplo de que é possível alterar os valores dos objetos,


mesmo que eles sejam declarados como atributos finais. A instrução botao.setText(“novo
rotulo do botao”) causará a alteração do rótulo do objeto e, consequentemente, do valor
armazenado por ele. Na linha 25 temos outro exemplo, dessa vez aplicada ao vetor, o qual
tem seus valores alterados. Já na linha 19 temos um exemplo de uso do modificador final
no parâmetro do método. Neste caso, a posição recebida não poderá ser alterada dentro
do escopo do método.

2.3.7. Modificador native

A linguagem de programação orientada a objetos Java oferece o modificador native,


capaz de combinar códigos de outras linguagens como, por exemplo, C/C++, com uma
aplicação Java. A utilização desse modificador será exclusiva para declaração de protótipos
de métodos em classes Java, os quais re-utilizarão códigos implementados em outras
linguagens. Apesar de passar despercebido por muitos programadores, o modificador native
torna-se útil quando há a necessidade de reaproveitar programas desenvolvidos em outras
linguagens que possuem códigos extensos e/ou de regra de negócio complexa. Para usar
o modificador native é preciso seguir o padrão de programação Java native Interface (JNI),
que permite chamar funções de códigos nativos a partir de uma JVM. É importante destacar
que o uso do JNI requer alguns cuidados para que a linguagem Java não perca duas de
suas principais vantagens: portabilidade e segurança.

Aplicações que fazem uso de métodos nativos ficam dependentes do sistema


operacional e do hardware onde o código nativo foi compilado, impedindo a portabilidade da
aplicação, pois diferente do Java, muitos compiladores de outras linguagens de programação
como C/C++ geram código executável de acordo com o sistema operacional e plataforma de
hardware. Além disso, a JVM permite apenas o acesso restrito à memória na qual um objeto
tenha direito, enquanto linguagens como C/C++ conferem acesso irrestrito à memória, o

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 86


que pode causar sérios riscos de segurança durante a execução de uma aplicação.

Para exemplificar o uso do modificador native e do JNI, será apresentado um exemplo


para exibir uma frase no dispositivo de saída padrão a partir de uma função imprimir(), a
partir de um código Java. A Figura 68, apresenta a classe OlaMundo contendo a declaração
de um método nativo implementado na linguagem C.

Figura 68. Exemplo de declaração do modificador native em linguagem de programação C.


Elaborado pelo autor.

Observe que na declaração do método imprimir() na linha 3 será utilizado o


operador native para indicar que o método será provido por um código nativo, o qual será
executado a partir do método main() (linha 5). O bloco estático inicializa o carregamento da
biblioteca nativa contendo a implementação do método imprimir().  

2.3.8. Modificador synchronized

Tucker(2009) também discute sobre como o modificador pode ser utilizado em


trechos de código para garantir justamente que apenas uma tarefa irá executar esse trecho
a cada vez, sem que haja interrupção. Logo, se houver várias tarefas (threads) em execução
em um determinado instante, pode ser que uma das tarefas inicie a execução de um trecho
de código que exija atomicidade. Logo, o mesmo deverá ser executado até o fim sem que a
tarefa seja interrompida. Além disso, deverá garantir que só uma tarefa execute esse trecho
de código por vez.

Figura 69. Exemplo do modificador synchronized. Elaborado pelo autor.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 87


No exemplo da Figura 69, object representa o objeto que o monitor irá aplicar o
bloqueio. O monitor está presente em todos os objetos Java, e garante que o bloqueio
de um objeto será realizado para uma única tarefa a cada momento. Então a chamada
do especificador synchronized por uma tarefa em execução irá utilizar o monitor do
objeto para bloquear o trecho de código. Sendo que o object do exemplo normalmente
será substituído pela palavra reservada this para se referir ao objeto em execução, isto
é, o uso do this normalmente irá representar o objeto que está em execução multitarefa
naquele instante em que for executar o trecho de código sincronizado. Se for aplicado o
modificador synchronized em um trecho de código e uma tarefa conseguir o bloqueio do
objeto, então todas as demais tarefas que tentarem executar o mesmo trecho de código (já
bloqueado) serão colocadas no estado bloqueado.
Outra possibilidade será utilizar o modificador synchronized em um método,
sinalizando que todo o código contido neste método terá sua execução sincronizada. Métodos
sincronizados serão equivalentes a um trecho de código sincronizado envolvendo todo o corpo
desse método e utilizando o objeto corrente this da execução multitarefa, como explicado
no parágrafo anterior. No entanto, quando for utilizado o especificador synchronized nos
métodos, o objeto corrente this será definido automaticamente de forma implícita, ou seja,
sem a existência explícita de código para essa definição. Um exemplo poderá ser visto
na Figura 70.

Figura 70. Exemplo de declaração do modificador synchronized. Elaborado pelo autor.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 88


O uso do especificador synchronized em um método garante que se duas
ou mais threads tentarem executar esse método, como, por exemplo, os métodos
transfere(), saque() e deposito() da Figura 70 a primeira tarefa que iniciar a execução terá
o bloqueio e executará o seu conteúdo do início ao fim, sem ser interrompida, enquanto
as outras tarefas permanecerão esperando sua vez de executar esse método. Quando a
tarefa que obteve o bloqueio completar a execução do método sincronizado, o método será
desbloqueado e outra tarefa que estiver aguardando iniciará sua execução, bloqueando
novamente esse trecho de código.

Esse comportamento é particularmente útil no exemplo do método transfere().


Neste caso, quando uma tarefa iniciar a execução, terá o bloqueio e executará os
métodos saque() e depósito() sem ser interrompida, enquanto as outras tarefas permanecerão
esperando sua vez de executar o método transfere().

2.3.9. Modificador volatile

O modificador volatile evita que qualquer alteração de variável compartilhada entre


múltiplos threads seja realizada no cache local de um thread. O volatile será aplicado
exclusivamente em variáveis e seu uso só terá sentido quando essas forem compartilhadas
entre threads. Tal modificador é pouco difundido entre os programadores e raramente
detalhado na literatura. Os desenvolvedores usualmente utilizam o synchronized para
bloquear o acesso a objetos e métodos compartilhados, enquanto o modificador volatile
permite o bloqueio de variáveis de tipos primitivos e, também, o de objetos.

Quando uma variável volatile sofrer qualquer mudança de valor por algum thread,
tal alteração será realizada diretamente na memória principal. Em um bloco ou método
sincronizado, qualquer alteração de valor de uma variável será realizada na memória cache
da JVM. Esta ação, em algumas situações, pode levar a uma inconsistência de dados
quando um thread realizar a leitura em uma variável compartilhada. Para exemplificar o
efeito do uso do modificador volatile, a Figura 71 apresenta um exemplo da ausência deste
operador em uma variável num, à qual é compartilhada entre dois threads. Por outro lado,
a Figura 73 exibe o mesmo código, porém fazendo uso desse modificador.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 89


Figura 71. Código da classe NonvolatileTest. Elaborado pelo autor.

Por se tratar de uma aplicação com múltiplas threads cujo escalonamento é de


responsabilidade do sistema operacional, uma possível saída da execução do código da
Listagem 71 é apresentado na Figura 72.

Figura 72. Saída da execução do código da Figura 70. Elaborado pelo autor.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 90


Figura 73. Código da classe volatileTest. Elaborado pelo autor.

Pode-se notar que os valores exibidos pela Thread1 e pela Thread2 são 10 e 20,
respectivamente. Isto ocorre porque a modificação será realizada apenas no cache local
dos threads. Para que ambas as threads leiam e escrevam na mesma variável num alocada
na memória principal, é preciso adicionar o modificador volatile na declaração da variável.
Deste modo, ao executar o código da Figura 73, obterá um resultado semelhante ao
apresentado na Figura 74.

Figura 74. Saída da execução do código da Figura 73. Elaborado pelo autor.

Com a adição do modificador volatile à variável num, a Thread2, em algumas


execuções, passará a exibir o valor 10 atribuído pela Thread1, pois ambas as threads
passam a acessar a mesma variável diretamente na memória principal da JVM.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 91


3. CONSTRUTORES

Segundo Furgeri (2018), na linguagem Java se um construtor não for definido, será
assumido um construtor default da própria linguagem, em que as variáveis serão inicializadas
com os conteúdos default, onde as variáveis numéricas receberão zero, valores lógicos
receberão false e objetos receberão null. O construtor deverá possuir sempre o mesmo
nome de sua classe e será sintaticamente semelhante a um método, quando for declarado.
Uma classe poderá conter de 0 a N construtores declarados ou definidos, dependendo
das suas necessidades. Usaremos normalmente, um construtor para fornecer valores
iniciais para as variáveis de instâncias definidas pela classe ou para executar algum outro
procedimento de inicialização necessário à criação de um objeto totalmente formado.
Será possível declarar seu próprio construtor a fim de especificar como objetos
de uma classe devem ser inicializados. A seguir, demonstraremos uma classe com vários
construtores sobrecarregados que permitem que objetos dessa classe sejam inicializados
de diferentes maneiras. Para sobrecarregar construtores, simplesmente forneça múltiplas
declarações de construtor com assinaturas diferentes.

3.1. Classe Time com Construtores Sobrecarregados

O construtor padrão da classe Time1 na Figura 75 inicializou hora, minuto e segundo


para seus valores zero padrão (isto é, meia-noite na data/hora universal). O construtor
padrão não permite que clientes da classe inicializem a data/hora com valores não zero

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 92


específico.

As variáveis de instância private int hora, minuto e segundo da classe Time1


nas linhas de 4 a 6, representam a hora no formato de data/hora universal (formato de
relógio de 24 horas em que as horas estão no intervalo de 0 a 23, e minutos e segundos
estão no intervalo 0 a 59). Time1 contém os métodos public setTime nas linhas 10 a 22),
toUniversalString (linhas 25 a 28) e toString (linhas 30 a 35). Esses métodos também são
chamados de serviços public ou interface public que a classe fornece para seus clientes.

Figura 75. Declaração da classe Time1. Elaborado pelo autor.

A classe Time2 das Figuras 76, 77, 78 e 79 contém cinco construtores sobrecarregados
que fornecem maneiras convenientes de inicializar objetos. Nesse programa, quatro dos
construtores invocam um quinto, o qual, por sua vez, garante que o valor fornecido para
hora está no intervalo de 0 a 23, e os valores para minute e second estão, cada um, no
intervalo de 0 a 59. O compilador invoca o construtor apropriado correspondendo o número,
tipos e a ordem dos tipos dos argumentos especificados na chamada do construtor com o
número, tipos e a ordem dos tipos dos parâmetros especificados em cada declaração de
construtor. A classe Time2 também fornece os métodos set() e get() para cada variável de

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 93


instância.

Figura 76. Classe Time2 com construtores sobrecarregados. Elaborado pelo autor.

Figura 77. Classe Time2 com construtores sobrecarregados (continuação). Elaborado pelo autor.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 94


Figura 78. Classe Time2 com construtores sobrecarregados (continuação).
Elaborado pelo autor.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 95


Figura 79. Classe Time2 com construtores sobrecarregados (continuação).
Elaborado pelo autor.

3.2. Chamando um construtor a partir de outra via this

As linhas 12 a 15, da Figura 76, declaram um assim chamado construtor sem


argumento que é invocado sem argumentos. Depois que você declarar quaisquer construtores
em uma classe, o compilador não fornecerá um construtor padrão. Esse construtor sem
argumento garante que os clientes da classe Time2 possam criar objetos Time2 com valores
padrão. Esse construtor simplesmente inicializa o objeto como especificado no corpo do
construtor. No corpo, introduzimos um uso da referência this que só é permitido como a
primeira instrução no corpo de um construtor. A linha 14, ainda da Figura 76, usa this na
sintaxe de chamada de método para invocar o construtor Time2 que recebe três parâmetros
(linhas 30 a 44,nas Figuras 76 e 77) com valores de zero para hora, minuto e segundo.
Utilizar a referência this como mostrado aqui é uma maneira popular de reutilizar código de

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 96


inicialização fornecido por outro dos construtores da classe em vez de definir um código
semelhante no corpo do construtor sem argumentos. Utilizamos essa sintaxe em quatro
dos cinco construtores Time2 para tornar a classe mais fácil de manter e modificar. Se for
necessário alterar a maneira como objetos da classe Time2 serão inicializados, somente o
construtor que os outros construtores da classe chamarem é que precisará ser modificado.

As linhas 18 a 21, da Figura 76, declaram um construtor Time2 com um parâmetro


int único que representa a hora que é passada com zero em minuto e segundo para o
construtor nas linhas 30 a 44, das Figuras 76 e 77. As linhas 24 a 27, da Figura 76 declaram
um construtor Time2 que recebe dois parâmetros int que representam a hora e minuto,
passados com zero de segundo para o construtor nas linhas 30 a 44. Como ocorre com o
construtor sem argumentos, cada um desses construtores invocará o construtor nas linhas
30 a 44 para minimizar a duplicação de código. As linhas 30 a 44 declaram o construtor
Time2, que recebe três parâmetros int que representam hora, minuto e segundo. Esse
construtor, validará e inicializará as variáveis de instância.

As linhas 47 a 51, na Figura 77, declaram um construtor Time2 que recebe uma
referência para outro objeto Time2. Os valores do argumento Time2 são passados para o
construtor de três argumentos nas linhas 30 a 44 para inicializar hora, minuto e segundo.
A linha 50, na Figura 77, poderia ter acessado diretamente os valores de hora, minuto e
segundo do argumento time com as expressões time.hora, time.minuto e time. segundo,
mesmo que hora, minuto e segundo sejam declarados como variáveis private da classe
Time2. Isso se deve a um relacionamento especial entre objetos da mesma classe. Veremos
mais adiante por que é preferível usar os métodos get.

O método setTime() nas linhas 56 a 70, nas Figuras 77 e 78, lança uma
IllegalArgumentException nas linhas 59, 62 e 65, na Figura 77, se quaisquer argumentos
do método estiverem fora do intervalo. Do contrário, ele definirá as variáveis de instância de
Time2 como os valores de argumento (linhas 67 a 69 da Figura 78).

3.3. Construtores e métodos Set e Get da classe Time2

Os métodos get() de Time2 serão chamados ao longo de toda a classe. Em particular,


os métodos toUniversalString e toString chamam os métodos getHora(), getMinuto() e
getSegundo() na linha 122 e nas linhas 129 e 130, da Figura 79, respectivamente. Em

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 97


cada caso, esses métodos poderiam ter acessado os dados privados da classe diretamente
sem chamar os métodos get(). Mas considere a possibilidade de alterar a representação
da hora de três valores int para um único valor int, a fim de representar o número total
de segundos que se passou desde a meia-noite. Se esse tipo de alteração fosse feito,
apenas os corpos dos métodos que acessam os dados private diretamente precisariam
ser alterados, especialmente, o construtor de três argumentos, o método setTime() e os
métodos set() e get() individuais para hora, minuto e segundo. Não haveria necessidade
de modificar o corpo dos métodos toUniversalString ou toString porque eles não acessam
os dados diretamente. Projetar a classe dessa maneira reduz a probabilidade de erros de
programação ao alterar a implementação da classe.

Os campos de uma classe private só poderão ser manipulados pelos seus


métodos. Uma manipulação típica talvez seja o ajuste do saldo bancário de um cliente, por
exemplo, uma variável de instância private de uma classe ContaBancaria, por um método
computarjuros(). Métodos set() também são comumente chamados métodos modificadores,
porque eles geralmente mudam o estado de um objeto, isto é, modificam os valores das
variáveis de instância. Os métodos get() também são comumente chamados de métodos
de acesso ou métodos de consulta.

3.4. Utilizando construtores sobrecarregados da classe Time2

A classe Time2Test da Figura 80 invoca os construtores Time2 sobrecarregados


nas linhas 8 a 12 e 24. A linha 8 invoca o construtor Time2 sem argumento. As linhas 9
a 12 demonstram como passar argumentos para os outros construtores Time2. A linha 9
invoca o construtor de argumento único que recebe um int nas linhas 18 a 21 da Figura
76. A linha 10 invoca o construtor de dois argumentos nas linhas 24 a 27 da Figura 76. A
linha 11 invoca o construtor de três argumentos nas linhas 30 a 44 da Figura 76 e 77. A
linha 12 invoca o construtor de argumento único que recebe um Time2 nas linhas 47 a 51
da Figura 77. Então, o aplicativo exibe as representações String de cada objeto Time2 para
confirmar que ele foi inicializado adequadamente nas linhas 15 a 19 na Figura 80. A linha
24 tenta inicializar t6 criando um novo objeto Time2 e passando três valores inválidos para
o construtor. Quando o construtor tentar usar o valor de hora inválido para inicializar hora
do objeto, ocorre uma IllegalArgumentException. Capturamos essa exceção na linha 26 e
exibimos a mensagem de erro, o que resulta na última linha da saída.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 98


Figura 80. Construtores sobrecarregados utilizados para inicializar objetos Time2. Elaborado pelo autor.

Figura 81. Saída da listagem do código da Figura 80. Elaborado pelo autor.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 99


4. HERANÇA

Furgeri(2018) começa o assunto com o seguinte questionamento, o que é herança?


A herança permite que uma nova classe estenda uma classe existente. A nova classe
herda os membros da classe que ela estende. O conceito de herança é a possibilidade
de representar algo que existe no mundo real. A técnica da herança utilizada em Java
possibilita o compartilhamento ou o aproveitamento de recursos definidos em outra classe
anteriormente. Outro termo que envolve herança é a especialização.

4.1. Generalização e Especialização

Quando uma classe herda características de outra classe, ela poderá implementar
partes específicas  não contempladas na classe original - superclasse - tornando-se
especializada em algum processo.
No mundo real, você poderá encontrar muitos objetos que serão versões
especializadas de outros objetos mais gerais. Por exemplo, o termo inseto descreve um tipo
muito geral de criatura com numerosas características. Porque gafanhotos e abelhas são
insetos, eles têm todas as características gerais de um inseto. Além disso, eles possuem
características especiais próprias. Por exemplo, o gafanhoto tem sua habilidade de saltar, e
o zangão tem seu ferrão. Gafanhotos e abelhas são versões especializadas de um inseto.
Isso é ilustrado na Figura 82.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 100


Figura 82. Abelhas e gafanhotos são versões especializadas de um inseto.
Fonte: VECTEEZY.

Além das características comuns dos insetos, o zangão tem suas próprias
características únicas, como a capacidade de picar e o gafanhoto tem suas próprias
características únicas, como a capacidade de pular.

4.2. Herança e o “é um” Relacionamento

Quando um objeto é uma versão especializada de outro objeto, existe um


relacionamento “é um” entre eles. Por exemplo, um gafanhoto é um inseto. Aqui estão
alguns outros exemplos do relacionamento “é um”:
• Um poodle é um cachorro
• Um carro é um veículo.
• Uma flor é uma planta.
• Um retângulo é uma forma.
• Um jogador de futebol é um atleta.

Quando existe um relacionamento “é um” entre objetos, significa que o objeto


especializado possui todas as características do objeto geral, além de características
adicionais que o tornam especial. Na programação orientada a objetos, a herança é usada
para criar um relacionamento “é um” entre classes. Isso permite estender os recursos de
uma classe criando outra classe que é uma versão especializada dela.

A herança envolve uma superclasse e uma subclasse. A superclasse é a classe


geral e a subclasse é a classe especializada. Você pode pensar na subclasse como uma
versão estendida da superclasse. A subclasse herdará campos e métodos da superclasse
sem que nenhum deles precise ser reescrito. Além disso, novos campos e métodos podem
ser adicionados à subclasse, e é isso que faz dela uma versão especializada da superclasse.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 101


Correndo o risco de confundi-lo com muita terminologia, deve-se mencionar que
as superclasses também são chamadas de classes base e as subclasses também são
chamadas de classes derivadas.

4.3. Aspectos básicos de Herança

A linguagem de programação Java dá suporte à herança permitindo que uma classe


incorpore outra classe em sua declaração. Com a utilização da palavra-chave extends, que
isso é feito. A subclasse traz, portanto, acréscimos (estende) à superclasse.

Começaremos com um exemplo que ilustra vários dos recursos-chaves de herança.


O programa a seguir cria uma superclasse chamada DuasDimensoes, que armazena a
largura e a altura de um objeto bidimensional e uma classe chamada Triangulo. Observe
como a palavra-chave extends é usada para criar uma subclasse na Figura 83.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 102


Figura 83. Criação de uma subclasse utilizando a palavra-chave extends. Elaborada pelo autor.

A saída do programa deverá ser como apresentado na Figura 84.

Figura 84. Saída da listagem do código da figura 83. Elaborada pelo autor.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 103


No programa apresentado no exemplo DuasDimensoes definirá os atributos de
uma forma bidimensional de forma genérica, como um quadrado, retângulo ou triângulo. A
classe Triangulo criará um tipo específico de DuasDimensoes, nesse caso, um triângulo.
Ela incluirá tudo que pertence a DuasDimensoes e adicionará o campo estilo, o método
area() e o método mostrarEstilo(). O estilo do triângulo será armazenado em estilo. Poderá
ser qualquer string que descreva o triângulo, como “cheio”, “contorno”, “transparente” ou
até algo como “símbolo de aviso”, “isósceles” ou “arredondado”. O método area() calculará
e retornará a área do triângulo e mostrarEstilo() exibe seu estilo.

Como a classe Triangulo inclui todos os membros de sua superclasse


DuasDimensoes, poderá acessar largura e altura dentro de area(). Dentro de main(), os
objetos t1 e t2 poderão referenciar largura e altura diretamente, como se eles fizessem
parte da classe Triangulo. A DuasDimensoes ainda que seja a superclasse de Triangulo,
ela também é uma classe autônoma totalmente independente. Ser a superclasse de uma
subclasse não significa que não poderá ser usada separadamente. A forma geral de uma
declaração class que herda uma superclasse é mostrada na Figura 85.

Figura 85. Sintaxe de uma declaração class que herda uma superclasse. Elaborada pelo autor.

Você só poderá especificar uma única superclasse para qualquer subclasse que
criar. A linguagem de programação Java não dá suporte à herança de várias superclasses
na mesma subclasse. Você poderá criar, no entanto, uma hierarquia de herança em que
uma subclasse passe a ser uma superclasse de outra subclasse. Nenhuma classe poderá
ser a superclasse de si mesma.

4.4. Acessando membros e Herança

Com frequência a variável de instância de uma classe será declarada como private
para não poder ser usada sem autorização ou adulterada. Quando for herdada uma classe,
não invalida a restrição de acesso private. Mesmo que uma subclasse inclua todos os
membros de sua superclasse, não poderão ser acessados os membros declarados como
private. Por exemplo, largura e altura foram tornadas privadas, em DuasDimensoes,

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 104


Triangulo não poderá acessá-las, conforme apresentado na Figura 86.

Figura 86. Membros privados de uma superclasse não podem ser acessados por uma subclasse. Elaborada
pelo autor.

No exemplo apresentado, a classe Triangulo, não será compilada, porque a referência


largura e altura dentro do método area() causa uma violação de acesso. Como largura e
altura foram declaradas como private em DuasDimensoes, só poderão ser acessadas por
outros membros de DuasDimensoes. As subclasses poderão ser acessá-las.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 105


Figura 87. As classes DuasDimensoes e Triangulo usando métodos acessadores para configurar e examinar
membros privados. Elaborada pelo autor.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 106


5. POLIMORFISMO

Segundo Deitel(2008), o polimorfismo permite “programar no geral” em vez de


“programar no específico”. Em particular, o polimorfismo permite escrever programas que
processam objetos que compartilham a mesma superclasse, direta ou indiretamente, como
se todos fossem objetos da superclasse; isso pode simplificar a programação. Considere o
exemplo de polimorfismo a seguir:

“Suponha que criaremos um programa que simula o movimento de vários tipos de


animais para um estudo biológico. As classes Peixe, Anfíbio e Pássaro representarão os
três tipos de animais sob investigação. Imagine que cada classe estenderá a superclasse
Animal, que contém um método mover() e mantém a localização atual de um animal como
coordenadas x-y. Cada subclasse implementará o método mover. Nosso programa mantém
um array Animal que contém referências a objetos das várias subclasses Animal. Para
simular os movimentos dos animais, o programa enviará a mesma mensagem a cada
objeto uma vez por segundo, a saber, mover. Cada tipo específico de Animal responde
a uma mensagem mover de uma maneira única, um Peixe poderia nadar um metro, um
Anfíbio poderia pular um metro e meio e um Pássaro poderia voar três metros. Cada objeto
saberá como modificar suas coordenadas x-y de forma adequada para seu tipo específico
de movimento. Contar com o fato de que cada objeto sabe “fazer a coisa certa”, isto é, faz
o que é apropriado a esse tipo de objeto, em resposta à mesma chamada de método é o
conceito chave do polimorfismo”. A mesma mensagem, nesse caso, mover, enviada a uma

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 107


variedade de objetos tem muitas formas de resultados, daí o termo polimorfismo.

5.1. Implementando Para Extensibilidade

Ainda conforme Deitel(2008), com o polimorfismo, podemos projetar e implementar


sistemas que são facilmente extensíveis. Novas classes poderão ser adicionadas com
pouca ou nenhuma modificação às partes gerais do programa, contanto que as novas
classes façam parte da hierarquia de herança que o programa processa genericamente.
As novas classes simplesmente se “encaixarão”. As únicas partes de um programa que
deverão ser alteradas serão aquelas que exigem conhecimento direto das novas classes
que adicionaremos à hierarquia. Por exemplo, se estendermos a classe Animal para criar a
classe Tartaruga, que poderá responder a uma mensagem mover deslizando uma polegada,
precisaremos escrever somente a classe Tartaruga e a parte da simulação que instancia
um objeto Tartaruga. As partes da simulação que dizem para que cada Animal se mova
genericamente poderão permanecer as mesmas.

5.2. Programando no Específico

Ocasionalmente, conforme trata Deitel(2008), ao realizar o processamento


polimórfico, precisaremos programar “no específico”. Nosso estudo de caso de Empregado
demonstra que um programa poderá determinar o tipo de um objeto em tempo de execução
e atuará sobre esse objeto de maneira correspondente.

No estudo de caso, decidimos que BasePlusEmpregadoComissão deverá receber


10% de aumento no salário-base. Assim, usaremos essas capacidades para determinar se
um objeto empregado particular é um BasePlusEmpregadoComissão. Se for, aumentaremos
o salário-base desse funcionário em 10%. Exemplo este trata na Figura

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 108


8.

Figura 88. Atribuindo referências de superclasse e subclasse a variáveis de superclasse e subclasse. Elabo-
rada pelo autor.

A saída para esta listagem do código da Figura 88 deverá ser apresentado na


Figura 89.

Figura 89. Saída para listagem de código da Figura 88. Elaborada pelo autor.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 109


Na Figura 88, as linhas 10 e 11 criam um objeto EmpregadoComissão e
atribuem sua referência a uma variável EmpregadoComissão. As linhas 14 a 16 criam
um objeto BasePlusEmpregadoComissão e atribuem sua referência a uma variável
BasePlusEmpregadoComissão. Essas atribuições são naturais. Por exemplo, o principal
propósito de uma variável EmpregadoComissão será armazenar uma referência a um objeto
EmpregadoComissão. As linhas 18 a 21 utilizam a empregadoComissão para invocar toString
explicitamente. Como empregadoComissão referencia um objeto EmpregadoComissão,
a versão de toString da superclasse EmpregadoComissão é chamada. De maneira
semelhante, as linhas 24 a 27 utilizam basePlusEmpregadoComissão para invocar toString
explicitamente no objeto BasePlusEmpregadoComissão. Isso invoca a versão de toString
da subclasse BasePlusEmpregadoComissão.

As linhas 30 e 31 atribuem então a referência ao objeto de subclasse


basePlusEmpregadoComissão a uma variável EmpregadoComissão da superclasse,
que as linhas 32 a 33 utilizam para invocar o método toString. Quando uma variável de
superclasse contém uma referência a um objeto de subclasse, e essa referência será
utilizada para chamar um método, a versão da subclasse do método será chamada. Daí,
empregadoComissão2.toString() na linha 33, na verdade chamará o método toString da
classe BasePlusEmpregadoComissão. O compilador Java permite esse “cruzamento”
porque um objeto de uma subclasse é um objeto da sua superclasse (mas não vice-versa).
Quando o compilador encontrar uma chamada de método feita por meio de uma variável,
ele determinará se o método poderá ser chamado verificando o tipo de classe da variável.
Se essa classe contiver a declaração adequada de método (ou herdar um), a chamada será
compilada. Em tempo de execução, o tipo do objeto que a variável referência determina o
método real a utilizar. Esse processo é chamado vinculação dinâmica.

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 110


SAIBA MAIS
Encapsulamento, Polimorfismo, Herança em Java

Para reforçar o estudo dos conceitos sobre programação orientada a objetos, trazemos
um artigo para você da DevMedia, onde serão mostrados os três principais conceitos do
paradigma da programação Orientada a Objetos, que são o encapsulamento, herança
e o polimorfismo.

Veja também como implementar os conceitos de programação orientada a objetos com


exemplos da linguagem de programação orientada a objetos Java. Vá para a internet
clicando no link abaixo e aproveite mais esse conteúdo!

https://www.devmedia.com.br/encapsulamento-polimorfismo-heranca-em-java/12991

REFLITA
“A pessoa que chega mais longe é geralmente aquela que está disposta a fazer e ousar.
O barco seguro nunca vai muito longe da margem”. (Dale Carnegie)

Com base neste pensamento de Dale Carnegie, um dos maiores escritores e pensado-
res, que ajudou e ainda ajuda centenas de milhares de pessoas a se desenvolverem
com seu legado deixado a mais de 74 anos, deixo essa mensagem como reflexão para
que você possa chegar mais longe, buscando novos conhecimentos e se desenvolven-
do continuamente.

Referência:
https://citacoes.in/citacoes/608433-dale-carnegie-a-pessoa-que-chega-mais-lon-
ge-e-geralmente-aquela/

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 111


CONSIDERAÇÕES FINAIS

Caro(a) aluno(a)!
Nosso objetivo foi trazer os conceito e exemplos para facilitar o entendimento de
um dos mais usado paradigma de programação na atualidade, a orientada a objetos.
Com uma rápida introdução aos conceitos e suas aplicações, você pôde ver uma breve
a utilização dos comandos de uma linguagem orientada a objetos e mesclando a estes
comandos tratamos sobre os conceitos envolvidos. Você pôde ver nesta unidade que a API
String possibilita a codificação de caracteres mais transparente.
Foi apresentado um estudo mais aprofundado e específico sobre os conceitos
avançados sobre classes e seus modificadores de acesso a classes e seus membros. Pôde
ver também que uma Classe é um código que descreve um tipo específico de objeto.  Pôde
ver que ele especifica os dados que um objeto poderá conter e as ações que um objeto
poderá executar, através do estudo de sua estrutura com exemplos práticos demonstrados
nesta unidade.
Com a utilização de estudos dirigidos, você pôde analisar os exemplos apresentados
que os modificadores de acesso são padrões de visibilidade de acessos às classes, atributos
e métodos. Você pôde verificar que os modificadores são palavras reservadas que não
poderão ser usadas como nome de métodos, classes ou atributos.
Outro ponto importante nessa unidade foi uma abordagem mais aprofundada a
respeito dos construtores e que é possível declarar seu próprio construtor a fim de especificar
como objetos de uma classe devem ser inicializados.
Além disso, também foi apresentada uma abordagem sobre herança com a
generalização e especialização. Você pôde constatar que linguagem de programação Java
sempre dará suporte à herança permitindo que uma classe incorpore outra classe em sua
declaração.
Neste livro, da disciplina de Programação Orientada a Objetos, veio acompanhada
de exemplos na linguagem de Programação Java. Recomendamos que você aprofunde
seus conhecimentos dessa linguagem através das dicas das leituras complementares, pois
a prática conduz ao aperfeiçoamento. Portanto estude e pratique constantemente! Somente
com dedicação ao estudo e a prática, você se tornará um excelente profissional.
Na próxima unidade vamos estudar sobre os Encapsulamento de Propriedades, a
utilização de Interfaces, Captura e Tratamento de Erros e Exceções e muito mais.
Não fique parado, e entre nesse mundo da Programação Orientado a Objetos com
a gente!
Até a próxima unidade!

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 112


MATERIAL COMPLEMENTAR

LIVRO
• Título: Programação orientada a objetos: Conceitos e técnicas
• Autor: Sérgio Furgeri
• Editora: Editora Érica
• Sinopse: Esta obra explica conceitos básicos de POO e
apresenta à instanciação de objetos, encapsulamento, escopo de
classe e instância, construtores e pacotes. Fornece visão geral
sobre recursos da orientação a objetos como herança, classes
abstratas e concretas, polimorfismo e interfaces. Discorre sobre
os elementos essenciais à compreensão da modelagem de
sistemas. Aborda recursos e ferramentas necessários em projetos
de sistemas orientados a objetos. Descreve os gerenciadores
de banco de dados e a linguagem SQL. Mostra as arquiteturas
em camadas, lógica e física. Contempla recursos de segurança
que devem estar presentes no desenvolvimento de sites, como
a validação de formulários, autenticação com login, sessões,
criptografia e arquivos de log. Comenta ainda a segurança de
transações na web, analisando algumas tecnologias importantes,
como certificação digital, OTP e IPT. O conteúdo pode ser
aplicado para os cursos técnicos ou de tecnologia em Informática,
Informática para Internet, Manutenção e Suporte em Informática,
Programação de Jogos Digitais, entre outros. Possui material de
apoio.

FILME/VÍDEO
Título: Design Patterns: Soluções para Problemas em Projetos
Orientados a Objetos.
Ano: 2018.
Sinopse: Nesse pocket vídeo abordaremos os padrões de
projetos na sua essência. Não é o objetivo deste pocket ensinar
a implementar os padrões de projetos em uma determinada
linguagem de programação, pelo contrário, a proposta é justamente
esquecer linguagem ou mesmo código e focar no que realmente
os padrões de projeto se propõe a ser. Iniciaremos conhecendo
um pouco da história da programação orientada a objetos e na
sequência a história dos padrões de projeto. Conheceremos um
pouco sobre o GOF (Gang of Four) e qual a sua parcela de “culpa”
na criação destes padrões. Em seguida veremos os 23 padrões e
sua classificação em criacionais, estruturais e comportamentais. É
fato que ninguém se torna um especialista em padrões de projetos
com apenas 45 minutos de vídeo por este motivo encerramos
nosso pocket com uma lista de referências para dar continuidade
aos estudos, algumas destas referências são leituras obrigatórias
para todo aquele que quer de fato se tornar um desenvolvedor
especializado em orientação a objetos, independente da linguagem.

Link do vídeo:
https://www.devmedia.com.br/design-patterns-solucoes-para-
problemas-em-projetos-orientado-a-objetos/31266

UNIDADE III Pilares da Orientação a Objetos e seus Comandos 113


UNIDADE IV
Trabalhando com Interfaces,
Tratamento de Erros e Novos
Paradigmas
Professor Mestre Ricardo Vieira

Plano de Estudo:
1. ENCAPSULAMENTO DE PROPRIEDADES
2. UTILIZANDO INTERFACES
3. CAPTURA E TRATAMENTO DE EXCEÇÕES
4. DESENVOLVIMENTO EM CAMADAS
5. CONSIDERAÇÕES FINAIS
6. REFERÊNCIAS

Objetivos de Aprendizagem:
● Conceituar e contextualizar a importância da utilização do encapsulamento de
propriedades.
● Compreender os tipos de interfaces que podem ser usadas em uma aplicação.
● Estabelecer a importância da captura e tratamento das exceções.
● Conhecer o desenvolvimento em camadas e alguns padrões de Desenvolvimento.

114
INTRODUÇÃO

Esta unidade inicia os estudos com uma breve introdução ao conceito e a utilização
do encapsulamento dentro da linguagem orientada a objetos. Você verá nesta unidade que
o encapsulamento é um mecanismo de programação que vincula o código e os dados que
ele trata, e isso mantém os dois seguros contra a interferência e a má utilização externa.

Com o estudo mais aprofundado sobre a utilização de interfaces. Você verá que
elas funcionam de maneira bastante similar a classes abstratas, porém não permitirão
implementações de nenhum método, contendo apenas a especificação deste.

E verá também que captura e tratamento das exceções indica um problema que
ocorre quando um programa for executado. O nome “exceção” sugere que o problema
ocorrerá com pouca frequência, se a “regra” é: uma instrução normalmente executará
corretamente, então o problema representará a “exceção à regra”.

Você terá uma abordagem mais aprofundada a respeito de desenvolvimento em


camadas. Será apresentada uma introdução ao conceito de Design Patterns, que são
padrões de projetos, dentro da programação orientada a objetos. Poderão estudar o
MVC (Model, View and Controller), que é uma arquitetura de projeto onde seu objetivo é
separar seu código em três camadas fazendo com que cada área só trabalhe com itens que
competem a elas e muito mais.

Falta pouco! Você chegou à reta final!


Então vamos firmes aos estudos!  E tenham um ótimo aproveitamento.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 115


1. ENCAPSULAMENTO DE PROPRIEDADES

Segundo Tucker(2009), o encapsulamento é um mecanismo de programação


que vincula o código e os dados que ele trata, e isso mantém os dois seguros contra a
interferência e a má utilização externa. Em uma linguagem orientada a objetos, o código
e os dados podem ser vinculados de tal forma que uma caixa preta autônoma seja criada.
Dentro da caixa, estão todo o código e os dados necessários. Quando o código e os dados
são vinculados dessa maneira, um objeto será criado. Em outras palavras, um objeto será
o dispositivo que dará suporte ao encapsulamento.

Dentro de um objeto, o código, os dados ou ambos, poderão ser privados ou


públicos. O código ou os dados privados só serão conhecidos e acessados por outra parte
do objeto. Isto é, o código ou os dados privados não poderão ser acessados por uma parte
do programa que exista fora do objeto. Quando o código ou os dados forem públicos, outras
partes do programa poderão acessá-los mesmo que estejam definidos dentro de um objeto.
Normalmente, as partes públicas de um objeto serão usadas para fornecer uma interface
controlada para os elementos privados do objeto.

Tucker(2009) ainda trata sobre a unidade básica de encapsulamento da linguagem


de programação Java chamada classe. Os conceitos de classe foram examinados com
mais detalhes anteriormente na unidade três, mas vale uma recapitulação para aumentar

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 116


a fixação do conceito. Uma classe define a forma de um objeto. Ela especificará tanto os
dados quanto o código que operará sobre eles. A linguagem Java usará uma especificação
de classe para construir objetos. Os objetos serão instâncias de uma classe. Logo, uma
classe será essencialmente um conjunto de planos que especificam como construir um
objeto. O código e os dados que constituem uma classe serão chamados de membros
da classe. Especificamente, os dados definidos pela classe serão chamados de variável
membro ou variáveis de instância. Os códigos que operam sobre esses dados serão
chamados de métodos membro ou apenas métodos.

1.1. As vantagens da utilização do encapsulamento

Conforme descreve Deitel (2008), a utilização do encapsulamento fornecerá uma


série de vantagens, não apenas pelo fato de ocultar certos detalhes de implementação,
mas por tornar o código mais legível, minimizar os erros de programação, restringir o
conteúdo das variáveis e facilitar a ampliação do código em função de novas atualizações.
Um programador ao instanciar uma classe poderá, por exemplo, realizar atualizações, ou
até mesmo modificações internas, sem que o usuário da classe se dê conta disso.

Para determinar o nível de acesso dos elementos de uma classe, serão usados os
qualificadores de acesso, já citados em unidade anteriores:
• public: um nível sem restrições, equivalente a não encapsular, ou seja, se uma
variável for definida como pública, não será possível realizar o encapsulamento;
• private: o nível de maior restrição em que apenas a própria classe poderá ter
acesso às variáveis e/ou métodos;
• protected: um nível intermediário de encapsulamento em que as variáveis e
métodos poderão ser acessados pela própria classe ou por suas subclasses;
• package: nível em que a classe poderá ser acessada apenas por outras classes
pertencentes ao mesmo pacote.

Por meio das restrições de acesso é possível assegurar que certas variáveis de
instância tenham valores restritos que só poderão ser acessados a partir da própria classe,
mantendo certa segurança com relação à integridade do valor armazenado.
Conforme demonstrado até aqui, as variáveis declaradas na classe foram
acessadas diretamente pelos objetos por meio da sintaxe nome_do_objeto.nome_da_
variável ou diretamente por meio da classe quando o atributo era estático. Considerando

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 117


o encapsulamento, o conteúdo das variáveis será acessado por métodos públicos get() e
set().
Esse processo enfatiza a separação entre os aspectos externos de um objeto (aqueles
que deverão estar acessíveis aos demais) e seus detalhes internos de implementação.
Através do encapsulamento poderá ser estabelecida uma interface bem definida para
interação do objeto com o mundo externo (interfaces públicas), isolando seus mecanismos
de implementação, que ficam confinados ao próprio objeto, como foi dito anteriormente.
Desta forma, o encapsulamento garante maior flexibilidade para alterações destes
mecanismos (implementação dos métodos), já que este é um aspecto não acessível aos
clientes externos. Todo e qualquer acesso aos métodos do objeto só poderá ser conseguido
através de sua interface pública, conforme ilustra a Figura 90.

Figura 90. Representação de acesso a métodos de um objeto. Elaborada pelo autor.

1.2. Atributos Privados

Conforme Furgeri(2018), no sistema do banco, cada objeto da classe Funcionario


possui um atributo para guardar o salário do funcionário que ele representa, conforme
Figura 91.

Figura 91. Exemplo de uma classe Funcionario. Elaborada pelo autor.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 118


O atributo salario poderá ser acessado ou modificado por código escrito em qualquer
classe que esteja no mesmo diretório que a classe Funcionario. Portanto, o controle desse
atributo é descentralizado.

Para identificar algum erro relacionado à manipulação dos salários dos funcionários,
será necessário verificar o código de todos os arquivos da pasta onde a classe Funcionario
estiver definida. Quanto maior o número de arquivos, menos eficiente será a manutenção
da aplicação. Poderemos obter um controle centralizado tornando o atributo salario privado
e definindo métodos para implementar todas as lógicas que utilizam ou modificam o valor
desse atributo.

Figura 92. Exemplo de uma classe Funcionario com o atributo privado salario. Elaborada pelo autor.

Um atributo privado só poderá ser acessado ou alterado por código escrito dentro
da classe na qual ele foi definido. Se algum código fora da classe Funcionario tentar acessar
ou alterar o valor do atributo privado salario, um erro de compilação será gerado.

Definir todos os atributos como privado e métodos para implementar as lógicas de


acesso e alteração será quase uma regra da orientação a objetos. O intuito é ter sempre
um controle centralizado dos dados dos objetos para facilitar a manutenção do sistema e a
detecção de erros.

O papel de alguns métodos poderão ser o de auxiliar outros métodos da mesma


classe. E muitas vezes, não será correto chamar esses métodos auxiliares de fora da sua
classe diretamente. No exemplo da Figura 93, o método descontaTarifa() é um método auxiliar
dos métodos deposita() e saca(). Além disso, ele não deverá ser chamado diretamente,
pois a tarifa só deverá ser descontada quando ocorrer um depósito ou um saque.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 119


Figura 93. Exemplo de uma classe Conta com o método descontaTarifa. Elaborada pelo autor.

Para garantir que métodos auxiliares não sejam chamados por código escrito fora
da classe na qual eles foram definidos, poderemos torná-los privados, acrescentando o
modificador private.

Figura 94. Método privado descontaTarifa. Elaborada pelo autor.

Qualquer chamada ao método descontaTarifa() realizada fora da classe Conta vai


gerar um erro de compilação.

1.3. Métodos Públicos

Ainda conforme Furgeri(2018), os métodos que deverão ser chamados a partir de


qualquer parte do sistema deverão possuir o modificador de visibilidade public. Assim é
apresentado na Figura 95.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 120


Figura 95. Exemplo de métodos públicos deposita e saca. Elaborada pelo autor.

1.4. Getters e Setters

Segundo Schildt(2013), na linguagem de programação Java, há uma convenção de


nomenclatura para os métodos que têm como finalidade acessar ou alterar as propriedades
de um objeto.
Segundo essas convenções, os nomes dos métodos que permitem as consultas
das propriedades de um objeto, deverão possuir o prefixo get. Analogamente, os nomes
dos métodos que permitem a alteração das propriedades de um objeto, deverão possuir o
prefixo set.
Na maioria dos casos, será muito conveniente seguir essa convenção, pois os
desenvolvedores Java já estão acostumados com essas regras de nomenclatura e o
funcionamento de muitas bibliotecas do Java depende fortemente desse padrão.

Figura 96. Exemplos de alteração das propriedades de um objeto com métodos get e set.
Elaborada pelo autor.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 121


2. UTILIZANDO INTERFACES

Knudsen(2005), trata sobre interface como sendo um “contrato” entre as classes.


Ela funciona de maneira bastante similar a classes abstratas, porém não permitirá
implementação de nenhum método, contendo apenas a especificação deste. A codificação
de uma interface também é semelhante à de uma classe, no entanto a declaração de uma
interface não se iniciará com a palavra reservada class. Um exemplo de codificação de uma
interface está presente na Figura 97.

Figura 97. Exemplos de sintaxe de interface. Elaborada pelo autor.

Veja que existe a palavra reservada “interface” no lugar de “class”, mas o arquivo
deverá ser salvo da mesma forma que uma classe. Vamos elaborar um exemplo mais
real para entendermos melhor. Veja o diagrama da Figura 98. Ele mostra duas possíveis
representações para uma interface de acordo com a UML:
• Uma representação similar à de uma classe (veja a interface DAO) contendo o
estereótipo <<interface>>. Isso permitirá diferenciar visualmente uma interface
de uma classe, já que a representação gráfica é a mesma. Essa representação

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 122


permitirá também visualizar o conteúdo interno (os métodos) da interface.
• Uma representação reduzida, em formato de um pequeno círculo (veja a
interface Estoque). Permite reduzir o tamanho de um diagrama, mas possui a
desvantagem de não permitir visualizar o conteúdo interno da interface.

Figura 98. Diagrama das interfaces DAO e Estoque. Elaborada pelo autor.

Esse diagrama representa:


• As classes Cliente e Fornecedor implementam a interface DAO, ou seja,
codificam todos os métodos especificados na interface DAO, no caso os métodos
incluir(), excluir() e localizar(). Por esse motivo, cada uma das classes possuirá
três métodos. As classes poderiam também implementar outros métodos não
especificados pela interface DAO.
• A classe Produto implementa a interface DAO (os métodos incluir(), excluir()
e localizar()) e a interface Estoque (o método baixar()). Como dissemos
anteriormente, apesar que a representação ser diferente, ambas serão
interfaces. Bem, se você não entendeu algo, não se preocupe. Isso ficará mais
claro ao codificar as interfaces e classes. Vamos iniciar pelas interfaces.

O Exemplo da Figura 99 apresenta a interface DAO.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 123


Figura 99. Representação da interface DAO. Elaborada pelo autor.

Conforme já foi mencionado, uma interface apenas contém a especificação dos


métodos, e nenhuma implementação. Ela apenas define os métodos que as classes que
a implementam serão obrigadas a conter (da mesma forma que a classe abstrata). Nesse
caso, a interface DAO está especificando os métodos incluir(), excluir() e localizar().
Da mesma forma, a interface Estoque contém apenas a especificação do método
baixar(). Veja sua codificação no exemplo da Figura 100.

Figura 100. Representação da interface Estoque. Elaborada pelo autor.

Neste ponto vamos apresentar a codificação resumida da classe Cliente. Veja o


exemplo na Figura 101.

Figura 101. Representação resumida da classe Cliente implements DAO.


Elaborada pelo autor.

Observe na linha 1 a forma utilizada em Java para vincular uma classe a uma
interface: trata-se do uso da palavra “implements”. Quando o compilador analisar essa linha,
ele identificará que a classe Cliente precisará implementar todos os métodos definidos na
interface DAO, inclusive seguindo a mesma assinatura. Se qualquer um dos métodos não
existir na classe Cliente, o compilador apresentará um erro. Em outras palavras, você poderá
interpretar a linha 1 como se fosse um contrato: “Eu, classe Cliente, aceito implementar

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 124


todos os métodos definidos na interface DAO”. Se a classe Cliente deixar de cumprir esse
contrato, ela se tornará inválida, não será compilada.

Na prática os métodos da classe Cliente (linhas 4 a 9) seriam codificados, isto é,


possuíram todo o código necessário para, por exemplo, inserir os dados do cliente num
banco de dados. Não será esse o objetivo no momento. Estamos interessados apenas em
entender o funcionamento de interfaces. A classe Fornecedor segue exatamente o mesmo
princípio da classe Cliente e por isso não apresentaremos sua codificação. Neste ponto
algo deverá ficar claro para você: o estabelecimento de contratos por meio de interfaces
permitirá padronizar o código de um sistema.

Uma vez que tanto a classe Cliente quanto a classe Fornecedor precisam
implementar os mesmos métodos (com os mesmos nomes), é possível construir um código
mais padronizado. Imagine se para inserir dados num banco de dados a classe Cliente
definisse o método inserir(), a classe Fornecedor definisse o método inclui() e outra classe
qualquer definisse o método inserirRegistro(). Veja que bagunça seria!

Como já dissemos, uma classe poderá implementar mais de uma interface ao mesmo
tempo. Esse é o caso da classe Produto, que implementará os métodos das interfaces DAO
e Estoque. O princípio será o mesmo; bastará adicionar todas as interfaces após a palavra
“implements”, separadas por vírgulas. Veja o exemplo na Figura 102.

Observe na linha 1 que a classe Produto implementa duas interfaces: DAO e


Estoque. Como já dissemos, os nomes das interfaces aparecerão separados por vírgula.
Por causa disso, a classe Produto deverá implementar os métodos das duas interfaces, o
que poderá ser visto nas linhas 4 a 11.

Figura 102. Representação da classe Produto implements DAO, Estoque.


Elaborada pelo autor.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 125


3. CAPTURA E TRATAMENTO DE EXCEÇÕES

Kalinovsky(2004) indica que uma exceção indica um problema que ocorre quando
um programa for executado. O nome “exceção” sugere que o problema ocorrerá com pouca
frequência, se a “regra” é: uma instrução normalmente executará corretamente, então
o problema representará a “exceção à regra”. O tratamento de exceção ajudará a criar
programas tolerantes às falhas que poderão resolver (ou tratar) exceções.

Em muitos casos, isso permitirá que um programa continue a executar como se


nenhum problema fosse encontrado. Por exemplo, o aplicativo PesquisaEstudantil ainda
exibe resultados (Figura 103), embora uma das respostas estivesse fora do intervalo.
Problemas mais graves poderão evitar que um programa continue executando normalmente,
exigindo que ele notifique o usuário sobre o problema e, então, termine. Quando a Java
Virtual Machine ou um método detectar um problema, como um índice de array inválido ou
um argumento de método inválido, ele lançará uma exceção, isto é, ocorrerá uma exceção.
Os métodos nas suas classes também poderão lançar exceções.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 126


Figura 103. Representação da classe PesquisaEstudantil. Elaborada pelo autor.

Este é um típico aplicativo de processamento de array (Figura 103). Queremos


resumir o número das respostas de cada tipo (isto é, 1 a 5). O array responder (linhas 9 e
10) é um array de inteiros de 20 elementos, contendo as respostas à pesquisa dadas pelos
alunos. O último valor no array é uma resposta intencionalmente incorreta (14). Quando um
programa Java for executado, a validade nos índices de elemento do array será verificada,
todos os índices deverão ser maiores ou iguais a 0 e menores que o comprimento do array.
Qualquer tentativa de acessar um elemento fora desse intervalo dos índices resultará em
um erro em tempo de execução que é conhecido como ArrayIndexOutOfBoundsException.
No final desta seção, discutiremos o valor de uma resposta inválida, demonstraremos a
verificação dos limites do array e introduziremos o mecanismo de tratamento de exceções
do Java, que pode ser usado para detectar e tratar ArrayIndexOutOfBoundsException.

3.1. A Instrução try

Kalinovsky(2004) também trata sobre exceções. E para lidar com elas, coloque
qualquer código que possa lançar uma exceção em uma instrução try (linhas 17 a 26 da

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 127


Figura 103). O bloco try (linhas 17 a 20) contém o código que poderá lançar uma exceção e o
bloco catch (linhas 21 a 26) contém o código que tratará a exceção se uma ocorrer. Poderão
haver muitos blocos catch para tratar com diferentes tipos de exceções que poderão ser
lançadas no bloco try correspondente. Quando a linha 19 incrementa corretamente um
elemento do array frequencia, as linhas 21 a 26 serão ignoradas. As chaves que delimitam
o corpo dos blocos try e catch serão obrigatórias.

3.2. Executando O Bloco catch

Quando o programa encontrar o valor invalido 14 no array respostas, ele tentará


adicionar 1 à frequencia[14], que estará fora dos limites do array, o array frequencia terá
apenas seis elementos (com índices de 0 a 5). Como a verificação dos limites de array
será executada em tempo de execução, a JVM vai gerar uma exceção, especificamente a
linha 19 lançará ArrayIndexOutOfBoundsException para notificar o programa sobre esse
problema. Nesse ponto, o bloco try terminará e o bloco catch começará a executar. Se você
declarou quaisquer variáveis locais no bloco try, agora elas estarão fora do escopo (e não
mais existirão), assim elas não estarão acessíveis no bloco catch.

conforme Kalinovsky(2004) indica em seu livro, o bloco catch declara um parâmetro


de exceção (e) do tipo IndexOutOfRangeException. O bloco catch poderá lidar com exceções
do tipo especificado. Dentro do bloco catch, você poderá usar o identificador do parâmetro
para interagir com um objeto que capturou a exceção.

3.3. O Método toString( ) Do Parâmetro De Exceção

Quando as linhas 21 a 26 (Figura 103) capturam a exceção, o programa exibirá uma


mensagem indicando o problema que ocorreu. A linha 23 chamará implicitamente o método
toString do objeto de exceção para obter a mensagem de erro, que está implicitamente
armazenada no objeto de exceção e exibi-la. Depois que a mensagem for exibida nesse
exemplo, a exceção será considerada tratada e o programa continua com a instrução
seguinte após as chaves de fechamento do bloco catch. Nesse exemplo, o fim da instrução
será alcançado (linha 27), assim o programa continua com o incremento da variável de
controle na linha 15.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 128


3.4. Detalhando Throwable

Como já foi dito, anteriormente, uma cláusula catch especificará um tipo de


exceção e um parâmetro. O parâmetro receberá o objeto de exceção. E conforme trata
Jacobi(2006), todas as exceções serão subclasses de Throwable, todas darão suporte aos
métodos definidos por Throwable. Alguns dos mais usados serão mostrados na Tabela
05. Dos métodos definidos por Throwable, printStackTrace( ) e toString( ) estão entre os
mais interessantes. Você poderá exibir a mensagem de erro padrão mais um registro das
chamadas de método que levam ao lançamento da exceção chamando printStackTrace( ), e
poderá usar toString( ) para recuperar a mensagem de erro padrão associada à exceção. O
método toString( ) também será chamado quando uma exceção for usada como argumento
de println( ). O programa na Figura 104 demonstra esses métodos.

Tabela 05. Métodos definidos por Throwable. Elaborado pelo autor.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 129


Figura 104. Representação da classe UseThrowableMethods. Elaborada pelo autor.

A saída desse programa será mostrada na Figura 105.

Figura 105. Saída do programa da Figura 104. Elaborada pelo autor.

O rastreamento de pilha exibirá a ordem em que os métodos que levam à exceção


serão chamados, com o último método sendo exibido no topo. Aqui, o rastreamento mostrará
que main( ) chamou genException( ). Já que genException( ) está no topo, será o método
em que a exceção ocorreu.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 130


4. DESENVOLVIMENTO EM CAMADAS

Goodrich(2013) trata padrões como conceitos pensados e desenvolvidos de forma


a manter um nível de organização mínimo entre projetos afins ou que usem tecnologias
afins. Isso torna a experiência de desenvolver software, mais tranquila, uma vez que muitos
outros já passaram por situações iguais ou semelhantes, e deu certo. Para os aprendizes
dos padrões, cabe a tarefa de aprendê-los mais rapidamente, e de forma mais concisa e
coesa. Neste capítulo, falaremos sobre os padrões de camadas usadas na grande maioria
das aplicações web, além de tratarmos mais a fundo sobre assuntos como MVC, JSF,
Persistência, Swing e suas principais características.

4.1. Design Patterns

Ainda conforme Goodrich(2013), Design Patterns ou padrões de


projetos são nada mais nada menos, que um modo de desenvolvimento. Segue-
se determinadas regras do padrão adotado para solução de determinado
problema, normalmente inerente à programação orientada à objetos.
É muito utilizado devido ao grau de abstração que se consegue através destas práticas,
tornando o código muito mais legível e de fácil manutenção e crescimento.

Um padrão de design clássico geralmente usado por aplicativos que precisam da

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 131


capacidade de manter várias visualizações dos mesmos dados. O padrão MVC depende
de uma separação clara de objetos em uma das três categorias:
• Modelos para manter dados;
• Exibições para exibir todos ou uma parte dos dados;
• Controladores para manipular eventos que afetam o modelo ou as exibições.

Devido a essa separação, várias visualizações e controladores podem interagir


com o mesmo modelo.

4.2. MVC (Model, View, Controller)

Goodrich(2013) cita que o MVC não foi criado para ser somente um padrão de
projeto, ele na verdade é uma arquitetura de projeto onde seu objetivo é separar seu código
em três camadas fazendo com que cada área só trabalhe com itens que competem à elas.
Trocando em miúdos, cada um só faz o que foi desenvolvido para fazer. Com o MVC você
facilmente transformará seu código de modo a ficar muito mais legível. Para utilizá-lo você
terá que ter em mente que haverá uma separação em seu código, as regras de negócio
ficarão separadas da lógica e da interface do usuário.

4.2.1. M de Model

O model, ou modelo, no padrão MVC serve para armazenar e persistir os dados.


O que seria isso? Toda comunicação com a base de dados. Os comandos crud (Create,
Read, Update and Delete - criação, consulta, atualização e destruição de dados) serão
feitas pelas classes deste tipo. Será utilizado para armazenar informações, trabalhando
como um espelho da tabela da base de dados. Como trabalhamos com objetos, os dados
serão persistidos como objetos.

4.2.2. V de View

O view, ou visão, no padrão MVC servirá apenas para exibir as informações


enviadas pelo controller, aqui não existirá nenhuma lógica ou regra de negócio, apenas a
interface do usuário.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 132


4.2.3. C de Controller

O controle faz exatamente o que o nome diz: controla. Ele é o responsável por fazer
o intermédio entre o modelo e a visão. É o responsável também por toda lógica do sistema.
Retornando somente os itens necessários para a comunicação entre o modelo e a visão.
Entre o usuário e a aplicação.

4.3. Trabalhando com Bancos de Dados usando o JDBC

Conforme Jacobi(2006), aplicativos comerciais geralmente armazenam dados


nos bancos de dados. Na maioria dos aplicativos corporativos, os RDBMS’s (Relational
Database Base Management Systems - Sistema de Gerenciamento de Banco de Dados
Relacional) são usados ​​como armazenamento de dados. Eles armazenam os registros
de dados nas tabelas. Cada registro (como o de um funcionário) é representado por uma
linha de tabela, que consiste em uma ou mais colunas ou campos de registro (por exemplo,
nome, endereço, data de contratação). RDBMS’s entendem a linguagem SQL.

A linguagem Java possui classes que permitem a conexão com bancos de dados,
as quais fazem parte do pacote JDBC (Java Database Connectivity), uma API (Aplication
Program Interface) que permite a comunicação com diversos Sistemas Gerenciadores de
Bancos de Dados, como Oracle, MySQL, SQL Server, PostgreSQL, entre outros. Existe
também a possibilidade de se utilizar uma bases de dados relacional open source chamado
Java DB, um banco criado a partir do projeto Apache Derby. Independentemente do banco
de dados usada, a linguagem padrão para manipulação dos dados é a SQL (Structured
Query Language).

Existe ainda a possibilidade de manipular bases de dados por meio de frameworks,


sem a necessidade de conhecer a linguagem SQL. No entanto, o processo de instalação e
configuração desses ambientes nem sempre é uma tarefa trivial, fato que pode gerar muitas
dúvidas aos leitores. No momento, o framework mais difundido e usado é o Hibernate.

4.3.1. Java Persistence API

Ainda conforme Jacobi(2006), a JPA (Java Persistence API) define uma maneira
padrão de mapear as classes Java para seus pares de bancos de dados relacionais. Esse

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 133


processo também é conhecido como mapeamento relacional de objeto (Object-Relational
Mapping - ORM). Um dos frameworks ORM de terceiros mais popular é o Hibernate,
mas esta lição é uma breve introdução ao JPA 2.0 padrão implementado por qualquer
servidor compatível com Java EE 6. Assim, recomendo que você procure saber mais sobre
o Hibernate, que em outras situações pode aumentar sua produtividade no processo de
persistência de dados ao banco de dados.

O JPA permite que você especifique e execute consultas e atualize dados sem
precisar gravar instruções SQL. A Java Persistence API permite mapear classes Java
para tabelas de banco de dados usando metadados e executar operações de criação,
recuperação, atualização e exclusão (CRUD) usando Java Persistence Query Language
(JPQL), Persistence Criteria API e consultas de banco de dados nativas na linguagem SQL.
A ideia é criar um modelo de domínio específico do aplicativo como um conjunto de classes
Java inter-relacionado e mapeá-lo para o armazenamento de dados correspondente (o
RDBMS).

Se uma classe Java marcada com a anotação @Entity não tiver um construtor de
argumento, você poderá chamá-la de entidade. Cada instância da entidade corresponde a
uma linha em uma tabela de banco de dados, conforme mostrado aqui: @Entity public class
Employee {
...
}

Se você iniciar com um banco de dados vazio, as ferramentas JPA permitem criar
tabelas de banco de dados baseadas em entidades Java. Você também poderá mapear
entidades Java para as tabelas de banco de dados existentes. Assim como as tabelas do
banco de dados, as entidades Java podem ter relacionamentos um-para-um (como uma
entidade Employee com uma entidade OfficeAddress correspondente), relacionamentos
um-para-um (como um cliente com muitos pedidos), muitos-para-um (o oposto de
relacionamentos um-para-muitos) e relacionamentos muitos-para-muitos (por exemplo,
uma UniversityClass tem muitos alunos matriculados, mas cada aluno pode se inscrever
em várias classes).

Cada classe de entidade deverá definir um campo contendo um valor exclusivo,


que é o equivalente de uma chave primária em uma tabela de banco de dados. A classe

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 134


EntityManager lidará com objetos. Antes de persistir os dados, você poderá validar os
valores usando o Bean Validation API.

Embora o JPQL forneça uma sintaxe semelhante a SQL baseada em string para
trabalhar com entidades, a mais recente API Criteria permite que você construa consultas
dinamicamente a partir de objetos fortemente tipados.

4.4. Introdução Ao Java Server Faces (JSF)

Jacobi(2006) também trata sobre o Java Server Faces como uma grande evolução
na época de sua criação. o JSF chegou pela primeira vez no estágio de tecnologia da Internet
em meados de 1999 como o novo padrão para a criação de aplicativos da Web baseados
em Java, ele recebeu grande atenção da comunidade de desenvolvimento da Web Java EE
na época. As interfaces de usuário para esses aplicativos da Web, são geralmente criadas
com tecnologias como HTML, CSS, JavaScript e o DOM. Essas tecnologias não foram
desenvolvidas tendo em mente os aplicativos corporativos e, com uma pressão crescente
dos consumidores para fornecer aplicativos com recursos não totalmente descritos
ou suportados por essas tecnologias, os desenvolvedores estão procurando soluções
alternativas ou para estender os padrões.

O Java Server Faces (JSF) é uma estrutura de interface com o usuário (UI) para
aplicativos da Web Java. Ele foi projetado para aliviar significativamente a carga de gravar
e manter aplicativos executados em um servidor de aplicativos Java e renderizar suas
interfaces de usuário para um cliente de destino.

O JSF permite que as organizações e os consumidores aproveitem a tecnologia


mais recente à medida que surgem com impacto mínimo nos aplicativos JSF existentes. O
JSF também traz extrema reutilização de funcionalidade e aparência visual para a indústria
de software.

O diferencial que o JSF traz, é que outros frameworks semelhantes não possuem
o suporte de uma especificação padrão. Como o JSF faz parte da especificação padrão
J2EE, será uma prioridade para todos os principais fornecedores de ferramentas J2EE no
mercado (incluindo Oracle, IBM, Borland e Sun) suportá-lo, o que, por sua vez, garantirá
uma ampla adoção e boas ferramentas de apoio.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 135


SAIBA MAIS
Design Patterns: na teoria e na prática

Para reforçar o estudo dos conceitos de programação orientada a objetos, trazemos


a você um artigo da DevMedia onde serão mostrados os principais conceitos sobre
Design Pattern, dentro do paradigma da programação Orientada a Objetos. Este artigo
demonstrará como evitar o alto acoplamento, identificando um problema dentro de um
cenário apresentado e aplicando o Design Patterns correto para solucioná-lo, sem o
auxílio de qualquer framework.
Acesse o link abaixo e aproveite mais esse conteúdo!

https://www.devmedia.com.br/design-patterns-na-teoria-e-na-pratica/32168

REFLITA
“Algumas pessoas acham que foco significa dizer sim para a coisa em que você vai se
focar. Mas não é nada disso. Significa dizer não às centenas de outras boas ideias que
existem. Você precisa selecionar cuidadosamente.” (Steve Jobs).

Inspirado em uma das maiores mentes da computação, Steve Jobs, hoje é o dia certo
para estudar, trabalhar, buscar algo novo. Mas, não devemos fazer isso tentando abra-
çar o mundo, ou seja, tentando fazer tudo ao mesmo tempo, mas sim, fazendo uma coi-
sa de cada vez, porém de forma completa e totalmente envolvida. Assim, priorizar será
a competência que você deverá aprimorar, somente assim será capaz de ir além e fazer
coisas que outros não poderão fazer.
Hoje é o dia!
Faça o hoje valer a pena, fazendo boas escolhas!
Referência:
https://www.tecmundo.com.br/internet/3145-frases-impactantes-sobre-tecnologia-e-in-
formatica.htm

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 136


CONSIDERAÇÕES FINAIS

Caro (a) Aluno (a)!


Chegamos ao final desta unidade com satisfação de tê-lo aqui conosco, com o
sentimento de dever cumprido e de saber que você, querido(a) aluno (a), conseguiu chegar
até o fim. Parabéns!

Você pôde ver e estudar nesta unidade uma introdução ao conceito e a utilização
do encapsulamento dentro da linguagem orientada a objetos. Além de um estudo mais
aprofundado sobre a utilização de interfaces.

Você pode ver e estudar também que captura e tratamento das exceções indica
um problema que ocorre quando um programa for executado. Você teve também uma
abordagem mais aprofundada a respeito de desenvolvimento em camadas.

Caro (a) Aluno (a), mais uma vez gostaria de parabenizá-lo pelo esforço e a
dedicação para chegar até aqui. Desejo a cada um vocês todo o sucesso que a vida pode
lhes proporcionar.

Bons Projetos, um grande abraço, e até a próxima!

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 137


MATERIAL COMPLEMENTAR

LIVRO
Título: Padrões de Projetos: Soluções Reutilizáveis de Software
Orientados a Objetos
Autor: Erich Gamma, Richard Helm, Ralph Johnson, John
Vlissides.
Editora: Bookman Companhia Editora.
Sinopse: Capturando uma vasta experiência sobre o design de
software orientado a objetos, quatro designers de primeira linha
apresentam um catálogo de soluções simples e sucintas para
problemas comuns de projeto. Anteriormente não documentados,
esses 23 padrões permitem que os designers criem designs
mais flexíveis, elegantes e, por fim, reutilizáveis, sem precisar
redescobrir as próprias soluções de design.
Os autores começam descrevendo quais são os padrões e como
podem ajudá-lo a projetar software orientado a objetos. Em seguida,
eles nomeiam, explicam, avaliam e catalogam sistematicamente
projetos recorrentes em sistemas orientados a objetos. Com o
Designs Patterns como seu guia, você aprenderá como esses
padrões importantes se encaixam no processo de desenvolvimento
de software e como você pode aproveitá-los para resolver seus
próprios problemas de design com mais eficiência.
Cada padrão descreve as circunstâncias em que é aplicável,
quando pode ser aplicado em vista de outras restrições de projeto,
e as consequências e desvantagens de usar o padrão dentro
de um design maior. Todos os padrões são compilados a partir
de sistemas reais e são baseados em exemplos do mundo real.
Cada padrão também inclui código que demonstra como ele pode
ser implementado em linguagens de programação orientadas a
objetos, como C ++ ou Smalltalk.

FILME/VÍDEO
• Título: Introdução a Design Patterns
• Ano: 2017
• Sinopse: Neste curso conheceremos os Design Patterns: teremos
uma visão geral sobre padrões de projetos e princípios de design.
Também iniciaremos a construção de um código funcional em Java
no NetBeans para reservas de quartos, justificando a necessidade
de utilização do princípio de programar para uma interface e não
para uma implementação. Conheceremos os 23 Design Patterns
descritos no livro GOF, que serve de base para esse curso.

• Link do vídeo: https://www.devmedia.com.br/curso/introducao-


a-design-patterns/188

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 138


REFERÊNCIAS

Dcore você. 2018. Fotos de plantas de casas com fachadas. [https://www.dcorevoce.


com.br/wp-content/uploads/2016/07/Fotos-de-plantas-de-casas-com-fachadas-com-tijolos-
-claros.jpg], Acesso em: 29/09/2019.
DEITEL, Paul J.; DEITEL, Harvey M. Java: como programar. Pearson Educación, 2008.
DEITEL, Paul J.; DEITEL, Harvey M. Java: como programar. Pearson Educación, 2017.
DevMedia. 2013. Modificadores de Acesso do Java. [https://www.devme-
dia.com.br/modificadores-de-acesso-do-java/27065], Acesso em: 03/08/2019.
FURGERI, Sérgio. Java 8–Ensino Didático: Desenvolvimento e Implementação de
Aplicações. Editora Saraiva, 2018.
FURGERI, Sérgio. Java 8–Ensino Didático: Desenvolvimento e Implementação de
Aplicações. Editora Saraiva, 2018.
GOODRICH, Michael T.; TAMASSIA, Roberto. Estruturas de Dados & Algoritmos em
Java. Bookman Editora, 2013.
JACOBI, Jonas; FALLOWS, John R. Pro JSF and Ajax: building rich Internet componen-
ts. Apress, 2006.
KALINOVSKY, Alex. Covert Java: Techniques for Decompiling, Patching, and Reverse
Engineering. Pearson Higher Education, 2004.
KNUDSEN, Jonathan; NIEMEYER, Patrick. Learning Java. O’Reilly, 2005.
NANCE, Richard E. Simulation programming languages: an abridged history. In: Pro-
ceedings of the 27th conference on Winter simulation. IEEE Computer Society, 1995. p.
1307-1313.
Pereira, V. de N., 2017. Aula 01 - AWT (Abstract Window Toolkit). [https://www.ic.uni-
camp.br/~ra100621/class/2017.2/ALPOO_files/aula01.html], Acesso em: 01/08/2019.
PRESSMAN, Roger. Engenharia de Software, 7a. Edição. Rio de Janeiro: McGraw, 2011.
SCHILDT, Herbert; SKRIEN, Dale. Programação com java: uma introdução abrangente.
Bookman Editora, 2015.
SCHILDT, Herbert; SKRIEN, Dale. Programação com java: uma introdução abrangente.
Bookman Editora, 2013.
Serra, N., Relvas, S. e Macedo, 2003. Tipos Abstractos de Dados (TADs) e Java. Dispo-
nível em: [http://ltodi.est.ips.pt/atai/index_files/TADs em Java e Estruturas.pdf]. Acesso em:
01/08/2019.
Silveira, G., Silveira, P. e Lopes, S., 2006. FJ-11 - Java e Orientação a Objetos. [http://
www2.ic.uff.br/~celio/classes/prog2/caelum-java-objetos-fj11.pdf]. Acesso em: 01/08/2019.
Siqueira, F. e Pacheco, R., 2012. Mini-Curso de Java. [http://www.inf.ufsc.br/~frank.siquei-
ra/INE5612/Java/CursoJava.pdf]. Acesso em: 01/08/2019.
TUCKER, Allen; NOONAN, Robert. Linguagens de Programação: Princípios e Paradig-
mas. AMGH Editora, 2009.
VECTEEZY. Fotos de abelhas e gafanhotos. [https://pt.vecteezy.com/arte-vetorial/
443729-vespa-realista-isolado] [https://pt.vecteezy.com/arte-vetorial/443398-gafanhoto-
-realista-isolado], Acesso em: 29/09/2019.

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 139


CONCLUSÃO

Prezado (a) aluno (a),


Neste material, buscamos trazer para você os principais conceitos a respeito da
Programação Orientada a Objetos. Para tanto abordamos as questões históricas, definições
teóricas e, neste aspecto acreditamos que tenha ajudado a assimilar os conceitos pilares
desse paradigma de desenvolvimento.
Destacamos também a importância da criação de unidades de código mais próxima
da forma como pensamos e agimos, assim usando como base a linguagem JAVA. Você
também pode ver uma introdução a vários conceitos e aplicações tais como criação e
utilização de classes, objetos, operadores e construtores, todos tratados de maneira
especial, em capítulo específico no decorrer dos estudos.
Levantamos também aspectos sobre Herança, Polimorfismo e encapsulamento,
além de vários comandos indispensável para a boa condução do desenvolvimento usando
paradigmas Orientados a Objetos. Também vimos a correlação entre a análise OO e seu
desenvolvimento, processo necessário para converter a interpretação dos diagramas para
o código fonte da programação.
Ao pensarmos em uma organização de código estruturado segundo os preceitos
da Orientação à Objetos com JAVA, não poderíamos deixar de falar sobre as propriedades
avançadas do encapsulamento e o uso efetivo das interfaces. Um ponto muito importante
abordado neste livro foi uma introdução ao desenvolvimento baseado em camadas e as
vantagens dessa prática com o desenvolvimento Orientado a Objetos.
A partir de agora acreditamos que você já está preparado para seguir em frente
desenvolvendo ainda mais suas habilidades para criar e desenvolver produtos e marcas de
sucesso no mercado e realizar bons negócios. Mas não pare por aqui, continue estudando
e buscando conhecimento. Em nossa área de atuação, ou seja, na área de TI, sempre
estão sendo lançadas novas ferramentas, métodos, paradigmas e técnicas para otimizar e
desenvolver melhor nosso código fonte e porque não nosso desenvolvimento pessoal, por
isso não pare de estudar e absorver novos conhecimentos.

Até uma próxima oportunidade. Muito Obrigado!

UNIDADE IV Trabalhando com Interfaces, Tratamento de Erros e Novos Paradigmas 140

Você também pode gostar