Você está na página 1de 27

Curso de Qualificação Socioprofissional em

Programação de Software
Treinamento em programação de software, com
enfoque no acesso ao mercado de trabalho.

Tomo II - Módulo II
Disciplina: Orientação A Objeto
Java I E II

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
Sumário

Orientação A Objeto Java I E II


1. Fundamentos da Programação Orientada a Objetos em Java.............................. 3
2. Classes e Objetos ................................................................................................... 5
3. Métodos e Atributos ............................................................................................... 8
4. Herança................................................................................................................. 14
5. Polimorfismo ........................................................................................................ 17
6. Redefinição de Métodos ....................................................................................... 19
7. Classe Abstrata..................................................................................................... 20
Interface ................................................................................................................... 23

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
1. Fundamentos da Programação Orientada a Objetos em Java

A programação orientada a objetos (POO) está em prática há muitas décadas. Na década de


1960, os seus conceitos fundamentais foram introduzidos pela primeira vez através da construção de
classe na linguagem de programação. Simula na década de 1960, entretanto a técnica de programação
foi só foi aceita com o advento do Smalltalk-80 mais de uma década depois.
Neste contexto, houve muito desenvolvimento de lá até então, e é sob esse panorama que
veremos os conceitos básicos do uso das técnicas de orientação a objetos na linguagem Java, tais como
os próprios objetos, que são instâncias de classes, que determinam qual informação um objeto contém
e como ele pode manipulá-la. Bem como também um dos grandes diferenciais da programação
orientada a objetos, em relação a outros paradigmas de programação que também permitem a definição
de estruturas e operações sobre essas estruturas: o conceito de herança, mecanismo o qual definições
existentes podem ser facilmente estendidas.
Juntamente com a herança deve ser enfatizada a funcionalidade do polimorfismo, que permite
selecionar funcionalidades que um programa irá utilizar de forma dinâmica, durante sua execução,
dentre outros interessantíssimos conceitos práticos.
Dessa maneira, para fins didáticos, segue uma lista de verbetes, para que o aluno tenha, a priori, uma
visão geral; a posteriori sirvam para pesquisas mais aprofundadas, como também a título de
conhecimento, os seguintes:

● Classe representa um conjunto de objetos com características afins. Uma classe define o
comportamento dos objetos através de seus métodos, e quais estados ele é capaz de manter através
de seus atributos.
○ Subclasse é uma nova classe que herda características de sua(s) classe(s) ancestral(is).
● Objeto / instância de uma classe. Um objeto armazena estados através de seus atributos e reage a
mensagens enviadas a ele, se relaciona e envia mensagens a outros objetos. Exemplo de objetos da
classe Humanos: João, Maria, José.
● Atributo é uma característica do objeto. Basicamente a estrutura de dados da classe. Exemplos: para
um objeto 'Funcionário': nome, endereço, telefone, CPF; 'Carro': nome, marca, ano, cor; 'Livro': autor,
editora, ano. Os atributos possuem valores. Por exemplo, o atributo cor pode conter o valor azul. O
conjunto de valores dos atributos de um determinado objeto é chamado de estado.
● Método define habilidades do objeto. Bidu é uma instância da classe Cachorro, portanto tem habilidade
para latir, implementada através do método 'latir'. Em geral, um método em uma classe é apenas uma
definição e a ação só ocorre quando o método é invocado através do objeto, no caso Bidu. A utilização
de um método deve afetar apenas um objeto em particular: todos os cachorros podem latir, mas apenas

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
Bidu emite o latido quando seu método é executado. Normalmente, uma classe possui diversos
métodos, que no caso da classe Cachorro podem ser coma, morda, corra, etc.
● Mensagem é uma chamada a um objeto para executar um de seus métodos. Também pode ser
direcionada diretamente a uma classe.
● Herança é o mecanismo pelo qual uma classe pode estender outra classe ou ser estendida por outra
classe. O mecanismo de herança permite que uma classe (subclasse) compartilhe o código-fonte outra
classe (superclasse), aproveitando seus comportamentos (métodos) e variáveis possíveis (atributos).
As grandes vantagens deste mecanismo são:

1) organização do software;
2) evitar a duplicação desnecessária de código, o que pode levar a reduzir o tempo gasto para
desenvolver o projeto.

Generalização é o processo de herança, no qual é criada uma superclasse, a partir de subclasses já


existentes.
Especialização é o processo no qual é criada uma subclasse a partir de superclasse(s) já existentes.
Neste último caso, a herança é simples, quando uma subclasse herda características de uma única
superclasse; a herança é múltipla, quando a subclasse herda características de mais de uma
superclasse. Um exemplo de herança: Mamífero é super-classe de Humano. Ou seja, um Humano é um
mamífero. Observação: Nem todas as linguagens orientadas a objetos suportam a herança múltipla
(Ex.: Java).

● Associação é o mecanismo pelo qual um objeto utiliza os recursos de outro. Pode tratar-se de uma
associação simples "usa um" ou de um acoplamento "parte de". Por exemplo: Um humano usa um
telefone. A tecla "1" é parte de um telefone. A composição de objetos é um tipo de associação.
● Encapsulamento consiste na separação de aspectos internos e externos de um objeto. Este
mecanismo é utilizado amplamente para impedir o acesso direto ao estado de um objeto (seus
atributos), disponibilizando externamente os métodos que acessam (getters) e alteram (setters) estes
estados. Exemplo: você não precisa conhecer os detalhes dos circuitos de um telefone para utilizá-lo. A
carcaça do telefone encapsula esses detalhes, provendo a você uma interface mais amigável (os botões,
o monofone e os sinais de tom).
● Abstração é a habilidade de concentrar nos aspectos essenciais de um contexto qualquer, ignorando
características menos importantes ou acidentais. Na POO, uma classe é uma abstração de entidades
existentes no domínio do software.
● Polimorfismo consiste no princípio pelo qual duas ou mais classes derivadas de uma mesma
superclasse podem invocar métodos que têm a mesma identificação (assinatura) mas comportamentos
4

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
distintos, especializados para cada classe. De acordo com a literatura, existem quatro tipos de
polimorfismo que uma linguagem de programação pode ter (nem toda linguagem orientada a objeto
tem suporte para os quatro tipos de polimorfismo):

○ Universal:
■ Inclusão: um ponteiro para a classe mãe pode apontar para uma instância de uma classe filha
(exemplo em Java: "List lista = new LinkedList();" (tipo de polimorfismo mais básico que existe).
■ Paramétrico: se restringe ao uso de templates (C++, por exemplo) e generics (Java/C#).

○ Ad-Hoc:
■ Sobrecarga: duas funções/métodos com o mesmo nome mas assinaturas diferentes
■ Coerção: a linguagem que faz as conversões implicitamente (como por exemplo atribuir um int a um
float em C++, isto é aceito mesmo sendo tipos diferentes pois a conversão é feita implicitamente).
● Interface: é um contrato entre a classe e o mundo externo. Quando uma classe implementa uma
interface, ela está comprometida a fornecer o comportamento publicado pela interface
● Pacotes (ou Namespaces): são referências para a organização lógica de classes e interfaces

2. Classes e Objetos

imagem “A definição de uma classe em Java”

A primeira linha é um comando que inicia a declaração da classe. Após a palavra-chave class,
segue-se o nome da classe, que deve ser um identificador válido para a linguagem.
A definição de classes é o principal resultado da etapa de projeto de software. Em geral, esse
resultado é expresso em termos de alguma linguagem de modelagem, tal como UML.
Classe é um gabarito para a definição de objetos. Através da definição de uma classe, descreve-se que
propriedades — ou atributos — o objeto terá.
Além da especificação de atributos, a definição de uma classe descreve também qual o
comportamento de objetos da classe, ou seja, que funcionalidades podem ser aplicadas a objetos da
classe. Essas funcionalidades são descritas através de métodos. Um método é o equivalente a um
procedimento ou função e ele manipula apenas suas variáveis locais e os atributos que foram definidos
para a classe.

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
Nesse contexto, a definição da classe propriamente dita está entre as chaves { e }, na imagem
1.0, que delimitam blocos na linguagem Java. Este corpo da classe usualmente obedece à seguinte
sequência de definição:
● 1. As variáveis de classe (definidas como static), ordenadas segundo sua visibilidade: iniciando pelas
public, seguidos pelas protected, pelas com visibilidade padrão (sem modificador) e finalmente pelas
private.
● 2. Os atributos (ou variáveis de instância) dos objetos dessa classe, seguindo a mesma ordenação
segundo a visibilidade definida para as variáveis de classe. ● 3. Os construtores de objetos dessa classe.
● 4. Os métodos da classe, geralmente agrupados por funcionalidade. Adefinição de atributos de uma
classe Java reflete de forma quase direta a informação que estaria contida na representação da classe
em um diagrama UML. Para tanto, a sintaxe utilizada para definir um atributo de um objeto é:

onde
● o modificador é opcional, especificando a visibilidade diferente da padrão (public, protected ou
private), alteração da modificabilidade (final) e se o atributo está associado à classe (static);
● o tipo deve ser um dos tipos primitivos da linguagem Java ou o nome de uma classe;
● o nome deve ser um identificador válido da linguagem Java;
● o valor default é opcional; se presente, especifica um valor inicial para a variável.
Todo programa Java tem sua execução iniciada pelo método main, alguma das classes do programa
Java deverá conter um método main. Essa classe é chamada de classe principal.

imagem “primeiro exemplo de programa em java”

As palavras “public” e “static” que aparecem na definição do método main serão explicadas em aulas
futuras. Já a palavra “void”, assim como em C, indica que o método não possui retorno. O argumento
“String args[ ]” é um vetor de Strings formado por todos os argumentos passados ao programa na linha
de comando quando o programa é invocado. O comando “System. out.println ( )” é utilizado para
imprimir algo na tela.
Você deveria editar esse programa no bloco de notas e salvá-lo com o nome “Exemplo01.java” e, em
uma máquina com o Java Development Kit (JDK) instalado, compila-lo digitando no prompt comando:

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
“javac Exemplo01.java”. Esse comando geraria o arquivo bytecode com o nome “Exemplo01.class”.
Então, para executar o programa, deveria ser digitado no prompt comando: “java Exemplo01.class”.
Em Java, o nome do arquivo deve ser sempre igual ao nome da classe, seguida da extensão “.java”. No
caso do nosso exemplo, o nome do arquivo precisa ser “Exemplo01.java” porque o nome da classe é
“Exemplo01”.
Além disso, preste atenção! Java é case sensitive, ou seja, o compilador diferencia letras minúsculas de
maiúsculas.

2.Objetos são instâncias de classes. É através deles que (praticamente) todo o processamento ocorre
em sistemas implementados com linguagens de programação orientadas a objetos. O uso racional de
objetos, obedecendo aos princípios associados à sua definição conforme estabelecido no paradigma de
desenvolvimento orientado a objetos, é chave para o desenvolvimento de sistemas complexos e
eficientes.
Um objeto é um elemento que representa, no domínio da solução, alguma entidade (abstrata
ou concreta) do domínio de interesse do problema sob análise. Objetos similares são agrupados em
classes.
No paradigma de orientação a objetos, tudo pode ser potencialmente representado como um
objeto. Sob o ponto de vista da programação orientada a objetos, um objeto não é muito diferente de
uma variável normal. Por exemplo, quando se define uma variável do tipo int em uma linguagem de
programação como C ou Java, essa variável tem: um espaço em memória para registrar o seu estado
(valor); um conjunto de operações que podem ser aplicadas a ela, através dos operadores definidos na
linguagem que podem ser aplicados a valores inteiros.
Da mesma forma, quando se cria um objeto, esse objeto adquire um espaço em memória para
armazenar seu estado (os valores de seu conjunto de atributos, definidos pela classe) e um conjunto
de operações que podem ser aplicadas ao objeto (o conjunto de métodos definidos pela classe).
Um programa orientado a objetos é composto por um conjunto de objetos que interagem
através de “trocas de mensagens”. Na prática, essa troca de mensagens traduz-se na aplicação de
métodos a objetos.
As técnicas de programação orientada a objetos recomendam que a estrutura de um objeto e
a implementação de seus métodos devem ser tão privativos como possível. Normalmente, os atributos
de um objeto não devem ser visíveis externamente. Da mesma forma, de um método deve ser suficiente
conhecer apenas sua especificação, sem necessidade de saber detalhes de como a funcionalidade que
ele executa é implementada.
Encapsulação é o princípio de projeto pelo qual cada componente de um programa deve agregar
toda a informação relevante para sua manipulação como uma unidade (uma cápsula). Aliado ao conceito
de ocultamento de informação, é um poderoso mecanismo da programação orientada a objetos.
7

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
Ocultamento da informação é o princípio pelo qual cada componente deve manter oculta sob
sua guarda uma decisão de projeto única. Para a utilização desse componente, apenas o mínimo
necessário para sua operação deve ser revelado (tornado público).
Na orientação a objetos, o uso da encapsulação e ocultamento da informação recomenda que
a representação do estado de um objeto deve ser mantida oculta. Cada objeto deve ser manipulado
exclusivamente através dos métodos públicos do objeto, dos quais apenas a assinatura deve ser
revelada. O conjunto de assinaturas dos métodos públicos da classe constitui sua interface operacional.
Dessa forma, detalhes internos sobre a operação do objeto não são conhecidos, permitindo que
o usuário do objeto trabalhe em um nível mais alto de abstração, sem preocupação com os detalhes
internos da classe. Essa facilidade permite simplificar a construção de programas com funcionalidades
complexas, tais como interfaces gráficas ou aplicações distribuídas.

3. Métodos e Atributos

Métodos são essencialmente procedimentos que podem manipular atributos de objetos para os
quais o método foi definido. Atributos estáticos são atributos que contêm informações inerentes a uma
classe e não a um objeto em específico. Por isso são também conhecidos como atributos ou variáveis
de classe.
Por exemplo, suponha que quiséssemos ter um atributo que indicasse a quantidade de contas
criadas. Esse atributo não seria inerente a uma conta em específico, mas a todas as contas. Assim, seria
definido como um atributo estático. Para definir um atributo estático em Java, basta colocar a palavra
static entre o qualificador e o tipo do atributo.
O mesmo conceito é válido para métodos. Métodos estáticos são inerentes à classe e, por isso,
não nos obrigam a instanciar um objeto para que possamos utilizá-los. Para definir um método como
estático, basta utilizar a palavra static, a exemplo do que acontece com atributos. Para utilizar um
método estático devo utilizar o nome da classe acompanhado pelo nome do método. Por exemplo, o
código abaixo apresenta exemplos de uso dos métodos da classe Math a fim de ilustrar a utilização de
métodos estáticos.

imagem “Utilização de métodos estáticos da classe Math”

Além dos atributos de objetos, métodos podem definir e manipular variáveis locais; também
podem receber parâmetros por valor através da lista de argumentos. A forma genérica para a definição
de um método em uma classe é
8

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
onde,
● o modificador (opcional) é uma combinação de: public, protected ou private;abstract oufinal;e static.
● o tipo é um indicador do valor de retorno, sendo void se o método não tiver um valor de retorno;
● o nome do método deve ser um identificador válido na linguagem Java;
● os argumentos são representados por uma lista de parâmetros separados por vírgulas, onde para
cada parâmetro é indicado primeiro o tipo e depois (separado por espaço) o nome.

Uma boa prática de programação é manter a funcionalidade de um método simples,


desempenhando uma única tarefa. O nome do método deve refletir de modo adequado a tarefa
realizada. Se a funcionalidade do método for simples, será fácil encontrar um nome adequado para o
método. Como ocorre para a definição de atributos, a definição de métodos reflete de forma quase
direta a informação que estaria presente em um diagrama de classes UML, a não ser por uma diferença
vital: o corpo do método. Métodos de mesmo nome podem co-existir em uma mesma classe desde que
a lista de argumentos seja distinta, usando o mecanismo de sobrecarga. O exemplo a seguir ilustra a
definição de uma classe de nome Ponto2D:

Um Objeto dessa classe tem dois atributos privativos que definem as coordenadas do ponto
bidimensional, x e y — nesse caso, as coordenadas são valores inteiros. A Classe tem dois construtores.

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
O primeiro deles recebe dois argumentos, também de nome x e y, que definem as coordenadas do
ponto criado. Para diferenciar no corpo do construtor os parâmetros dos atributos, estes têm seu nome
prefixado pela palavra-chave this. O segundo construtor ilustra outro uso da palavra-chave this. Esse
construtor não recebe argumentos e assume, portanto, o ponto tem como coordenadas a origem, ou
seja, o ponto (0,0). O corpo desse construtor poderia ser simplesmente:

A alternativa apresentada usa a forma

que equivale a “use o construtor desta mesma classe que recebe dois argumentos inteiros, passando
os valores aqui especificados”. Finalmente, a classe define um método público para calcular a distância
entre o ponto que invocou o método (this) e outro ponto especificado como o argumento p. Nesse caso,
como não há risco de confusão, não é preciso usar a palavra-chave this antes dos atributos da
coordenada do objeto. Assim, as expressões que calculam distX e distY equivalem a

A expressão de retorno ilustra ainda a utilização de um método estático da classe Math do pacote
java.lang para o cômputo da raiz quadrada. Usualmente, métodos definidos em uma são aplicados a
objetos daquela classe. Há no entanto situações nas quais um método pode fazer uso dos recursos de
uma classe para realizar sua tarefa sem necessariamente ter de estar associado a um objeto
individualmente.
Para lidar com tais situações, Java define os métodos da classe, cuja declaração deve conter o
modificador static. Um método estático pode ser aplicado à classe e não necessariamente a um objeto.
Exemplos de métodos Estáticos em Java incluem os métodos para manipulação de tipos primitivos
definidos nas classes Character,Integer e Double, todas elas do pacote java.lang,assim como todos os
métodos definidos para a classe Math.
O método main: Toda classe pode também ter um método main associado, que será utilizado pelo
interpretador Java para dar início à execução de uma aplicação. Ao contrário do que acontece em C e
C++, onde apenas uma função main deve ser definida para a aplicação como um todo, toda e qualquer
classe Java pode ter um método main definido.
Apenas no momento da interpretação o main a ser executado é definido através do primeiro argumento
(o nome da classe) para o programa interpretador. O método main é um método associado à classe e
não a um objeto específico da classe — assim, ele é definido como um método estático. Adicionalmente,
deve ser um método público para permitir sua execução a partir da máquina virtual Java. Não tem valor
de retorno, mas recebe como argumento um arranjo de strings que corresponde aos parâmetros que

10

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
podem ser passados para a aplicação a partir da linha de comando. Essas características determinam a
assinatura do método:

Mesmo que não seja utilizado, o argumento de main deve ser especificado. Por exemplo, a definição da
classe Ponto2D poderia ser complementada com a inclusão de um método para testar sua
funcionalidade:

O nome do parâmetro (args) obviamente poderia ser diferente, mas os demais termos da
assinatura devem obedecer ao formato especificado. Esse argumento é um parâmetro do tipo arranjo
de objetos da classe String. Cada elemento desse arranjo corresponde a um argumento passado para
o interpretador Java na linha de comando que o invocou. Por exemplo, se a linha de comando for

o método main(String[] args)da classe Xyz vai receber, nessa execução, um arranjo de três elementos
na variável args com os seguintes conteúdos:

● em args[0], o objeto String com conteúdo "abc";


● em args[1], o objeto String com conteúdo "123";
● em args[2], o objeto String com conteúdo "def".

Como o método main é do tipo void, ele não tem valor de retorno. No entanto, assim como
programas desenvolvidos em outras linguagens, é preciso algumas vezes obter uma indicação se o
programa executou com sucesso ou não. Isto é principalmente útil quando o programa é invocado no
contexto de um script do sistema operacional.

Em Java, o mecanismo para fornecer essa indicação é o método System.exit(int). A invocação


desse método provoca o fim imediato da execução do interpretador Java. Tipicamente, o argumento de
exit() obedece à convenção de que '0' indica execução com sucesso, enquanto um valor diferente de 0
indica a ocorrência de algum problema.
11

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
Dessa maneira, uma vez que estejam definidas quais serão as classes que irão compor uma aplicação,
assim como qual deve ser sua estrutura interna e comportamento, é possível criar essas classes em
Java.
Na Unified Modeling Language (UML), a representação para uma classe no diagrama de classes
é tipicamente expressa na forma gráfica, como mostrado na Figura 1.1. Como se observa nessa figura,
a especificação de uma classe é composta por três regiões: o nome da classe, o conjunto de atributos
da classe e o conjunto de métodos da classe.

Ex.:
Figura 1.1: Uma classe em notação UML.

O nome da classe é um identificador para a classe, que permite referenciá-la posteriormente —


por exemplo, no momento da criação de um objeto. O conjunto de atributos descreve as propriedades
da classe. Cada atributo é identificado por um nome e tem um tipo associado. Em uma linguagem de
programação orientada a objetos pura, o tipo é o nome de uma classe. Na prática, a maior parte das
linguagens de programação orientada a objetos oferecem um grupo de tipos primitivos, como inteiro,
real e caráter, que podem ser usados na descrição de atributos. O atributo pode ainda ter um valor
default opcional, que especifica um valor inicial para o atributo.

Nesse contexto, é notável que os métodos definem as funcionalidades da classe, ou seja, o


que será possível fazer com objetos dessa classe. Cada método é especificado por uma assinatura,
composta por um identificador para o método (o nome do método), o tipo para o valor de retorno e
sua lista de argumentos, sendo cada argumento identificado por seu tipo e nome.
Através do mecanismo de sobrecarga (overloading), dois métodos de uma classe podem ter
o mesmo nome, desde que suas assinaturas sejam diferentes. Tal situação não gera conflito pois o
compilador é capaz de detectar qual método deve ser escolhido a partir da análise dos tipos dos
argumentos do método. Nesse caso, diz-se que ocorre a ligação prematura (early binding) para o
método correto.

12

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
O modificador de visibilidade pode estar presente tanto para atributos como para métodos.
Em princípio, três categorias de visibilidade podem ser definidas: público, denotado em UML pelo
símbolo +: nesse caso, o atributo ou método de um objeto dessa classe pode ser acessado por qualquer
outro objeto (visibilidade externa total); privativo, denotado em UML pelo símbolo -: nesse caso, o
atributo ou método de um objeto dessa classe não pode ser acessado por nenhum outro objeto
(nenhuma visibilidade externa);
protegido, denotado em UML pelo símbolo #: nesse caso, o atributo ou método de um objeto dessa
classe poderá ser acessado apenas por objetos de classes que sejam derivadas dessa através do
mecanismo de herança (ver Seção 1.3).
No Exemplo 1, temos um código de um aplicativo mínimo geralmente exibe a string “Alo Mundo” na
tela. O código Java abaixo mostra um exemplo de um aplicativo mínimo Java.

Ex.1:

A seguir é dada uma breve descrição desses elementos de programa:


• public - O método main() pode ser acessado por qualquer classe.
• static - Uma palavra-chave que informa ao compilador que main() não requer a chamada de uma
instância dessa classe.
• void - Indica que nada é retornado por main(). Essa informação é importante pois Java realiza uma
verificação de tipo cuidadosa, que inclui a verificação dos métodos chamados, observando se eles
realmente retornam os tipos com os quais foram declarados.
• String args[] - A declaração de uma matriz do tipo String. Estes são os argumentos digitados na linha
de comando após o nome da classe,

Ex.:

13

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
4. Herança

O conceito de encapsular estrutura e comportamento em um tipo não é exclusivo da orientação


a objetos; particularmente, a programação por tipos abstratos de dados segue esse mesmo conceito.
O que torna a orientação a objetos única é o conceito de herança.
Herança é um mecanismo que permite que características comuns a diversas classes sejam
fatoradas em uma classe base, ou superclasse. A partir de uma classe base, outras classes podem ser
especificadas. Cada classe derivada ou subclasse apresenta as características (estrutura e métodos) da
classe base e acrescenta a elas o que for definido de particularidade para ela.
Sob o ponto de vista prático da orientação a objetos, a herança constitui um mecanismo muito
inteligente de aproveitar código. É através da herança que os objetos podem compartilhar métodos e
atributos. Assim, podemos criar uma nova classe fazendo com que esta herde os métodos e atributos
de uma outra classe, tornando-a uma classe “filho” da classe que a gerou. A grande vantagem neste
caso é que reutilizaremos todo o código já implementado na classe pai, restando apenas implementar
os métodos e atributos que a diferenciam da classe pai.
Há várias formas de relacionamentos em herança:
Extensão: a subclasse estende a superclasse, acrescentando novos membros (atributos e/ou métodos).
A superclasse permanece inalterada, motivo pelo qual este tipo de relacionamento é normalmente
referenciado como herança estrita.

Especificação: a superclasse especifica o que uma subclasse deve oferecer, mas não implementa
nenhuma funcionalidade. Diz-se que apenas a interface (conjunto de especificação dos métodos
públicos) da superclasse é herdada pela subclasse.

14

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
Combinação de extensão e especificação: a subclasse herda a interface e uma implementação padrão
de (pelo menos alguns de) métodos da superclasse. A subclasse pode então redefinir métodos para
especializar o comportamento em relação ao que é oferecido pela superclasse, ou ter que oferecer
alguma implementação para métodos que a superclasse tenha declarado, mas não implementado.
Normalmente, este tipo de relacionamento é denominado herança polimórfica. A última forma é, sem
dúvida, a que mais ocorre na programação orientada a objetos.
Algumas modelagens introduzem uma forma de herança conhecida como contração. Contração é uma
variante de herança onde a subclasse elimina métodos da superclasse com o objetivo de criar uma
“classe mais simples”. A eliminação pode ocorrer pela redefinição de métodos com corpo vazio. O
problema com este mecanismo é que ele viola o princípio da substituição, segundo o qual uma subclasse
deve poder ser utilizada em todos os pontos onde a superclasse poderia ser utilizada. Se a contração
parece ser uma solução adequada em uma hierarquia de classes, provavelmente a hierarquia deve ser
reanalisada para detecção de inconsistências (problema pássaros-pinguins). De modo geral, o
mecanismo de contração deve ser evitado.

O exemplo acima cria a classe Animal e duas classes derivadas de Animal. É importante observar
que nas classes derivadas temos a redefinição do método fazerBarulho(). Esta redefinição é classificada
como uma sobreposição (override) de métodos. O conceito de sobreposição somente pode ser
identificado e utilizado quando temos classes dispostas em um relacionamento de herança.
Para ilustrar adequadamente o conceito de herança, vamos criar uma classe para representar
as contas especiais de um banco. Em nosso exemplo, uma conta especial é um tipo de conta que
permite que o cliente efetue saques acima de seu saldo até um limite, ou seja, permite que o cliente
fique com saldo negativo até um dado limite. Assim, criaremos uma classe ContaEspecial que herdará
da classe Conta que criamos em aulas anteriores.
Adotaremos essa estratégia, já que uma ContaEspecial é um tipo de Conta que tem, além de todos os
atributos comuns a todas as contas, o atributo limite. Sendo assim, deve-se utilizar a palavra reservada
extends para que ContaEspecial herde de Conta suas características.
15

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
imagem”Código da classe ContaEspecial que herda da classe Conta”

Esse é o código da classe da classe ContaEspecial. Note na definição da classe a utilização da


palavra extends.
Nesse caso dizemos que ContaEspecial é uma subclasse ou classe filha de Conta. Podemos
também dizer que Conta é ancestral ou classe pai de ContaEspecial. Note que ContaEspecial define um
tipo mais especializado de conta. Assim, ao mecanismo de criar novas classes herdando de outras é
dado o nome de especialização.
E então suponha que tenhamos um outro tipo de conta: a ContaPoupanca. A ContaPoupanca
tem tudo o que a Conta tem com um método a mais que permite atribuir um reajuste percentual ao
saldo. Agora teríamos duas classes herdando da classe Conta Nesse contexto podemos dizer que a
classe Conta generaliza os conceitos de ContaEspecial e ContaPoupanca.

Esse é o código da classe ContaPoupanca. Note que ela herda as características da classe Conta
e apenas implementa um novo método: reajustar.
Quando visualizamos uma hierarquia partindo da classe pai para filhas, dizemos que houve uma
especialização da superclasse. Quando visualizamos partindo das classes filhas para as classes
ancestrais, dizemos que houve uma generalização das subclasses. Seu IDE nos sinalizará com erros nas
duas classes pois não definimos construtores para as duas subclasses que acabamos de gerar.
Caso você não tenha definido um construtor em sua superclasse, não será obrigado a definir
construtores para as subclasses, pois Java utilizará o construtor padrão para a superclasse e para as
subclasses. Porém, caso haja algum construtor definido na superclasse, obrigatoriamente você precisará
criar ao menos um construtor para cada subclasse. Vale ressaltar que os construtores das subclasses
utilizarão os construtores das superclasses pelo uso da palavra reservada super.

16

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
imagem “Construtor da classe ContaEspecial “

imagem “Construtor da classe ContaPoupanca”

Dessa forma, o conceito de herança nos permite criar uma classe a partir de outra. Assim,
quando temos um conjunto de classes com características comuns, utilizamos o conceito de herança
para agrupar essas características em vez de repetirmos suas implementações várias vezes.

5. Polimorfismo

Polimorfismo é o princípio pelo qual duas ou mais classes derivadas de uma mesma superclasse
podem invocar métodos que têm a mesma identificação (assinatura) mas comportamentos distintos,
especializados para cada classe derivada, usando para tanto uma referência a um objeto do tipo da
superclasse. Esse mecanismo é fundamental na programação orientada a objetos, permitindo definir
funcionalidades que operem genericamente com objetos, abstraindo-se de seus detalhes particulares
quando esses não forem necessários.
Para que o polimorfismo possa ser utilizado, é necessário que os métodos que estejam sendo
definidos nas classes derivadas tenham exatamente a mesma assinatura do método definido na super-
classe; nesse caso, está sendo utilizado o mecanismo de redefinição de métodos (overriding). Esse
mecanismo de redefinição é muito diferente do mecanismo de sobrecarga de métodos, onde as listas
de argumentos são diferentes.
No caso do polimorfismo, o compilador não tem como decidir qual o método que será utilizado
se o método foi redefinido em outras classes — afinal, pelo princípio da substituição um objeto de uma
classe derivada pode estar sendo referenciado como sendo um objeto da superclasse. Se esse for o
caso, o método que deve ser selecionado é o da classe derivada e não o da superclasse.
Dessa forma, a decisão sobre qual dos métodos que deve ser selecionado, de acordo com o
tipo do objeto, pode ser tomada apenas em tempo de execução, através do mecanismo de ligação
tardia. O mecanismo de ligação tardia também é conhecido pelos termos em inglês late binding, dynamic
binding ou ainda run-time binding.

17

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
Por exemplo:

É notável que de acordo com a opção escolhida no menu impresso, temos a criação de um
objeto diferente. Quando o usuário digita 2, por exemplo, é criada uma instância de ContaEspecial. Note
que a variável c é do tipo Conta mas, ainda assim, é possível atribuir a ela uma instância de
ContaPoupanca ou de ContaEspecial pois ambas herdam da classe Conta. Na última linha do código
apresentado, o método imprimirTipoConta() é chamado mas, sabemos que esse método foi
implementado na classe Conta e sobrescrito nas duas classes filhas assim, qual das implementações
será usada por essa chamada?
A resposta a essa pergunta vai depender da opção digitada pelo usuário! Por exemplo, caso o usuário
digite 2, a variável c receberá uma instância de ContaEspecial e obviamente nesse caso, na última linha
será chamado o método imprimirTipoConta() da classe ContaEspecial.
Bem como analogamente, caso o usuário digite a opção 1, será utilizado o método da classe Conta e,
caso digite 3, será utilizado o método da classe ContaPoupanca. Nesse exemplo, a mesma linha de
código pode ter um comportamento diferente, dependendo das circunstâncias. Isso é polimorfismo!

18

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
O polimorfismo pode ser obtido pela utilização dos conceitos de herança, sobrecarga de métodos e
sobrescrita de método, também conhecida como redefinição ou reescrita de método, que veremos a
seguir.

6. Redefinição de Métodos

Redefinição de métodos é suportado na programação orientada a objetos e está intimamente


conectado com Overloading (ou sobrecarga de operação, em português). A técnica de sobrescrita
permite reescrever um método em uma subclasse de forma que tenha comportamento diferente do
método de mesma assinatura existente na sua superclasse.
Para exeplificar o conceito de sobrescrita, vamos criar um método imprimirTipoConta() na
superclasse Conta e vamos sobrescrevê-lo nas duas subclasses da nossa hierarquia de exemplo
(ContaEspecial e ContaPoupanca). Esse método simplesmente imprimirá na tela uma mensagem de
acordo com o tipo da conta, ou seja, de acordo com o tipo do objeto ele imprimirá uma mensagem
diferente. A Figura 4.6 exibe apenas a linha de definição de cada classe e seu respectivo método
imprimirTipoConta() (omitimos o resto dos códigos das classes e as juntamos todas em uma única figura
por uma questão de espaço).

Repare nas linhas anteriores aos métodos ImprimirTipoConta das classes ContaEspecial e
ContaPoupança, há uma notação @Override. A notação @Override é inserida automaticamente pelo
NetBeans para indicar que esse método foi definido no ancestral e está sendo redefinido na classe atual.
A não colocação da notação @Override não gera erro, mas gera um aviso (Warning). Isso ocorre porque
entende-se que, quando lemos uma classe e seus métodos, é importante existir alguma forma de

19

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
sabermos se um certo método foi ou não definido numa classe ancestral. Assim a notação @Override
é fundamental para aumentar a legibilidade e manutenibilidade do código.
Métodos de mesmo nome podem ser declarados na mesma classe, contanto que tenham
diferentes conjuntos de parâmetros (determinado pelo número, tipos e ordem dos parâmetros). Isso é
chamado sobrecarga de método (DEITEL; DEITEL, 2010, p. 174).

Para que os métodos de mesmo nome possam ser distinguidos, Sobrecarga, eles devem
possuir assinaturas diferentes. A assinatura (signature) de um método é composta pelo nome do método
e por uma lista que indica os tipos de todos os seus argumentos. Assim, métodos com mesmo nome
são considerados diferentes se recebem um diferente número de argumentos ou tipos diferentes de
argumentos e têm, portanto, uma assinatura diferente.
Para exemplificar o conceito de sobrecarga, implementaremos na classe Conta um novo método
imprimirTipoConta que receberá como parâmetro uma String e imprimirá na tela o tipo da conta seguido
pela String recebida. Na Figura abaixo há dois métodos imprimirTipoConta da classe Conta.

Então agora se faz possível o entendimento de que o polimorfismo permite que um mesmo método seja
executado de formas diferentes de acordo com a classe do objeto que o aciona e com os parâmetros
passados para o método. De fato, o polimorfismo é conseguido pela implementação de conceitos como
herança, sobrecarga e sobrescrita de métodos. Esses conceitos nos permitem desenvolver códigos
mais reutilizáveis e elegantes. O entendimento desses conceitos é fundamental para desenvolver
programas realmente orientados a objetos.

7. Classe Abstrata

Procurando a palavra “abstração” em um dicionário da língua portuguesa, encontramos, como


definição, “ato de separar mentalmente um ou mais elementos de uma totalidade complexa (coisa,
representação, fato), os quais só mentalmente podem subsistir fora dessa totalidade”. Também
conhecida como Ocultamento da informação, a abstração é o princípio pelo qual cada componente deve
manter oculta sob sua guarda uma decisão de projeto única. Para a utilização desse componente,
apenas o mínimo necessário para sua operação deve ser revelado (tornado público). Possuímos o
recurso da abstração como forma de entender problemas tidos como complexos. Assim, diante de um
problema complexo, procuramos dividi-lo em problemas menores, e feito isso, resolvemos cada um
20

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
deles até encontrar a solução do problema inteiro. O termo “abstração”, aplicado ao desenvolvimento
de sistemas, é basicamente “só deve ser representado aquilo que vai ser usado”.
Já aprendemos que uma classe define as características e o comportamento de um conjunto de
objetos. Assim, os objetos são criados (instanciados) a partir de classes. Mas, nem todas as classes são
projetadas para permitir a criação de objetos. Algumas classes são usadas apenas para agrupar
características comuns a diversas classes e, então, ser herdada por outras classes. Tais classes são
conhecidas como classes abstratas. Às vezes é útil declarar classes – chamadas classes abstratas – para
as quais você nunca pretende criar objetos. Como elas só são usadas como superclasses em hierarquias
de herança, são chamadas superclasses abstratas.
Essas classes não podem ser usadas para instanciar objetos, porque são incompletas. Suas subclasses
devem declarar as “partes ausentes” para tornarem-se classes concretas, a partir das quais você pode
instanciar objetos (DEITEL; DEITEL, 2010, p. 309). As classes que não são abstratas são conhecidas
como classes concretas.
O conceito de classe abstrata está intimamente ligado ao conceito de herança estudados
anteriormente.
Para ilustrar o conceito de classe abstrata, voltemos ao nosso exemplo de contas bancárias. No exemplo
apresentado na aula sobre herança e polimorfismo, tínhamos as classes ContaEspecial e ContaPoupança
herdandas da classe Conta.
Agora, suponha que toda conta criada no nosso banco tenha que ser uma conta especial ou
uma conta poupança. Nesse caso, nunca teríamos uma instância da classe Conta,pois toda conta criada
seria uma instância de ContaEspecial ou de ContaPoupanca.
Nesse contexto surgem algumas perguntas: teria sentido criar a classe Conta? Por que criar uma classe
que nunca será instanciada?
A resposta à primeira pergunta é sim! A classe Conta continuaria existindo para organizar as
características comuns aos dois tipos de contas. Então, para garantir que a classe Conta exista, mas
nunca seja instanciada, essa classe deve ser criada como abstrata.
Para definir uma classe abstrata em Java, basta utilizar a palavra reservada abstract. A palavra abstract
deve ser inserida entre o qualificador de acesso e o nome da classe. a figura abaixo exibe o código da
classe Conta agora como classe abstrata.

21

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
imagem “ classe conta abstrata”

Note que a única diferença em relação ao código original é o uso da palavra abstract. A Figura
5.1 apresenta apenas os atributos e construtores da classe Conta, não apresentando os seus métodos.
Mas, vale ressaltar que a transformação de uma classe em abstrata não traz impacto para nenhum de
seus métodos e nem para os códigos das suas subclasses.
Uma classe abstrata não pode ser instanciada, ou seja, não há objetos que possam ser construídos
diretamente de sua definição. Por exemplo, a compilação do seguinte trecho de código:

geraria a seguinte mensagem de erro:

Geralmente, classes abstratas definem um conjunto de funcionalidades das quais pelo menos uma está
especificada, mas não definida — ou seja, contém pelo menos um método abstrato, como em:

22

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
Um método abstrato não cria uma definição, mas apenas uma declaração de um método que
deverá ser implementado em uma classe derivada. Se esse método não for implementado na classe
derivada, esta permanece como uma classe abstrata mesmo que não tenha sido assim declarada
explicitamente.
Dessa maneira, para que uma classe derivada de uma classe abstrata possa gerar objetos, os métodos
abstratos devem ser definidos em classes derivadas:

Interface

Uma interface modela um comportamento esperado, com sintaxe similar à de classes, mas
contendo apenas a especificação da funcionalidade que uma classe deve conter, sem determinar como
essa funcionalidade deve ser implementada. Pode-se entendê-la como uma classe que contenha apenas
métodos abstratos, um conjunto de declarações de métodos, sem as respectivas implementações. Uma
interface é parecida com uma classe; porém, em uma interface, todos os métodos são públicos e
abstratos e todos os atributos são públicos, estáticos e constantes. A sintaxe para criar uma interface é
muito parecida com a sintaxe para criar uma classe: public interface <nome_da_interface>.
por exemplo:

23

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
Repare que são quatro interfaces: Atleta, Corredor, Nadador e Ciclista; duas classes: Pessoa e
Triatleta. A implementação da classe Pessoa.
Note que Nadador, Corredor e Ciclista herdam de Atleta. A herança entre interfaces é feita da mesma
forma que a herança entre classes: utilizando a palavra reservada extends.

Embora uma classe não possa conter mais de uma super classe, a classe pode implementar mais de
uma interface. Uma interface Java é uma classe abstrata para a qual todos os métodos são
implicitamente abstract e public, e todos os atributos são implicitamente static e final. Em outros termos,
uma interface Java implementa uma “classe abstrata pura”.
A sintaxe para a declaração de uma interface é similar àquela para a definição de classes, porém seu
corpo define apenas assinaturas de métodos e constantes. Por exemplo, para definir uma interface
Interface1 que declara um método met1 sem argumentos e sem valor de retorno, a sintaxe é:

A diferença entre uma classe abstrata e uma interface Java é que a interface obrigatoriamente
não tem um “corpo” associado. Para que uma classe seja abstrata basta que ela seja assim declarada,
mas a classe pode incluir atributos de objetos e definição de métodos, públicos ou não. Na interface,
apenas métodos públicos podem ser declarados — mas não definidos. Da mesma forma, não é possível
definir atributos — apenas constantes públicas.

24

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
Enquanto uma classe abstrata é “estendida” (palavra chave extends) por classes derivadas, uma
interface Java é “implementada” (palavra chave implements) por outras classes.
Uma interface estabelece uma espécie de contrato que é obedecido por uma classe. Quando
uma classe implementa uma interface, garante-se que todas as funcionalidades especificadas pela
interface serão oferecidas pela classe.
Java não implementa herança múltipla. Então o conceito de interface surge como uma
alternativa. Uma interface define um conjunto de métodos sem suas implementações, de forma que
toda classe que implemente uma interface deve trazer implementações para todos os métodos definidos
em tal interface.

25

Rua Professor Ângela Pinto, 88, Sala 5 Torre - Recife - PE - CEP 50710-010 - Fone/FAX: (081) 9 8611 0999
CNPJ. 35.328.913/0001-16 - E-mail: admtec@admtec.org.br – nucleodeformacao@admtec.org.br
R. Profª Ângela Pinto, 88 – Sala 05 – Torre,
Recife/PE – CEP 50710-010
Fone: 81 98611-0999
nucleodeformacao@admtec.org.br

Você também pode gostar