Programação Orientada a Objetos
Faculdade de Computação
Faculdade de Computação
Revisão
Revisão
Prova 2
Prova 2
Marcelo Zanchetta do Nascimento
Material elaborado pela
Roteiro
Herança
Polimorfismo
Classes Abstrata
Interface
Exceção
Arquivos
Herança
Herança permite a criação de classes com base em uma
classe já existente.
Objetivo
: proporcionar o reuso de software
“Herança é a capacidade de reusar código pela
especialização de soluções genéricas já existentes”
• A ideia na herança é “ampliar” a funcionalidade de uma
classe
Todo objeto da subclasse também é um objeto da
superclasse, mas NÃO vice-versa
Herança
Herança representa um relacionamento de
generalização entre classes:
É-um
É um tipo de
Polígono Quadrilátero Triângulo Retângulo QuadradoÉ-um
Representação UML
A representação gráfica do conceito de herança, na linguagem
UML (Unified Modeling Language), é definida por retas com setas
apontando para a classe-mãe
Herança
Subclasse herda os membros da superclasse
Estes são tratados de forma semelhante a qualquer
outro membro da subclasse
Nem todos os atributos e métodos da superclasse são
obrigatoriamente acessíveis na subclasse - depende
dos modificadores de acesso
Modificador
private
na superclasse não permite
acesso direto dentro da subclasse
Herança
Funcionário
# nome: String # cpf: int
+ Funcionário (n:String, c:int) + getNome ( ): String
+ getCpf( ): int
Motorista
- numCarteira: int -dataExpiração: String
+ Motorista (n:String, c:int, cm:int, d:String)
+ getNumCarteira ( ): int + getDataExpiração( ): String
Engenheiro
- numCrea: int
+ Engenheiro (n:String, c:int, nc:int) + getNumCrea ( ): int Não se repete a declaração de atributos e métodos herdados!
Exemplo:
# = protegido,
Visível nas superclasse
e nas subclasses apenas
Herança: Super vs this
A palavra
this
é usada para referenciar membros de um
objeto
É obrigatória quando há ambiguidades entre variáveis locais e
de instância (atributos)
super() vs this()
super()
e
this()
são usados somente nos construtores
super()
: para chamar construtor na classe base a partir de
construtor de classe derivada
this()
: para chamar outro construtor dentro de outro construtor
de uma mesma classe
Polimorfismo
Habilidade de ter
muitas formas
Do Grego poly(muitas) + morpho(formas)
Habilidade de objetos de uma ou mais classes em
responder a uma mesma mensagem de forma diferente
– Métodos com mesmo nome, mas implementados de maneira
diferente
Permite obter códigos genéricos:
- Podem processar naturalmente diversos tipo de dados
- Podem processar os mesmos dados de maneiras diferentes
- Podem fazer um mesmo objeto ter comportamentos diferentes
Polimorfismo
Pode ocorrer de duas formas:
– Por sobrecarga
(Overloading)
– Por sobreposição (Overriding)
Sobrecarga
Regra
para sobrecarga de métodos:
- É permitida a criação de métodos com
nomes iguais
, mas os
métodos devem ter
assinaturas diferentes
A
assinatura
do método é composta pelo
nome
do método e pelos
tipos
dos seus argumentos, independente dos nomes dos argumentos
e do valor de retorno da função
Exemplos de assinaturas iguais:
float soma(float a, float b);
void soma(float op1, float op2);
Exemplo de assinatura diferente:
Sobrecarga
É implementada, normalmente, para métodos que devem
executar operações semelhantes, usando uma lógica
de programação diferente para diferentes tipos de dados
Exemplo:
public class Funções{
public int quadrado( int x )
{
return x * x;
}
public double quadrado( double y )
{
return y * y;
}
Sobrescrita
Permite a redefinição do funcionamento de uma função
herdada de uma classe base
- A classe derivada tem uma função com a
mesma assinatura
da
classe base, mas funcionamento diferente
– Função na classe derivada
sobrepõe
a função na classe base
Equipamentogravar
Câmera
gravar gravarSom
Gravar para a câmera é gravar imagem + som
Gravar para o
aparelho de som é gravar somente som
Sobrescrita
Regra
para sobrescrita:
– O método da subclasse deve ser declarado exatamente com o
mesmo nome, tipo de retorno e lista de parâmetros (inclusive a
ordem)
– O modificador de acesso pode mudar, mas o método na
subclasse não pode ser menos acessível do que o método da
superclasse
Sobrescrita
Exemplo:
Considere as seguintes classes public class ObjetoGeo {
...
public void desenha(Graphics g); }
public class Retangulo extends ObjetoGeo { ...
public void desenha (Graphics g) { g.drawRect (x, y, lado, lado2); }
}
public class Circulo extends ObjetoGeo { ...
public void desenha (Graphics g) { g.drawCircle (x, y, raio); } } A classe mãe especifica um método desenha
Cada classe filha fornece uma implementação diferente para a mesma especificação do método desenha
Sobrescrita
Exemplo:
...
for (int i = 0; i < desenhos.size(); ++i) { ObjetoGeo x = desenhos[i];
x.desenha(g); }
...
Na ocasião desta chamada, será decidido automaticamente qual implementação será invocada, dependendo do objeto: esta decisão é denominada “ligação
Classes abstratas
Classe abstrata
(ou virtual): é uma classe da qual
nunca são criadas instâncias (objetos)
– Ela existe apenas para
reunir características comuns
de seus
descendentes
– Ela serve como um
modelo
para criação de classes
descendentes
Classes abstratas
Classe Pessoa Atributos: nome: texto Métodos: incluir( ) alterar ( ) excluir ( ) Pessoa Cliente Vendedor endereço imprimir( ) grauVenda imprimirVendas( ) idade Super-Classe A classe Pessoa existe para reunir as características.
Um objeto efetivo dentro de uma loja deve ser cliente ou vendedor. Não
Métodos abstratos
Método abstrato:
É um método que só pode ser definido em uma classe
abstrata
Não é implementado na classe onde ele é definido
Deve ser
obrigatoriamente
implementado em toda classe
herdeira da classe abstrata
É usado, principalmente, para determinar um padrão para
todas as classes herdeiras
Declarar um método como abstrato é uma forma de obrigar o
programador a redefinir esse método em todas as subclasses
para as quais se deseja criar objetos
Métodos abstratos
Exemplo:
Observe que não faz sentido a classe Veículo ter implementação
desses métodos, pois em cada subclasse essas operações têm
public class Animal{
private String nome;
public Animal(String n) {
nome = n;
}
public void imp() {
System.out.println("Nome: "+nome);
}
public String getName() { return(nome); }
public void talk() {
System.out.println("Eu não falo");
}
}
public abstract class Passaro extends Animal{
public Passaro(String n) {
super(n);
}
public void talk() {
System.out.println("Piu piu");
}
}
public abstract class Mamifero extends Animal{
public Mamifero(String n) {
super(n);
}
public abstract void talk();
//talk não foi implementado
}
public class Cachorro extends Mamifero {
private String nome; // Nome do cachorro private String raça; // Raça do cachorro public Cachorro(String nome1, String raça1) {
// Chama o construtor da classe base super("Cachorro");
nome = nome1; // Nome fornecido raça =raça1; // Raça fornecida }
public void talk() {
System.out.println("Au, au"); }
}
public class TestaAbstracao {
public static void main(String[] args) {
// Cria um objeto cachorro
Cachorro cão = new Cachorro("Lassie", "Collie");
cão.talk(); }
Interface
Definição
:
Conjunto de
assinaturas de métodos
(sem
implementação)
Espécie de contrato firmado por uma classe
para garantir uma certa funcionalidade a
seus objetos
Interface
Em
Java
: classe abstrata pura
- Só tem
métodos abstratos
(sem implementações)
- Todos métodos são public e abstract
- Não tem atributos, a menos que sejam
constantes
- Todas variáveis são public, static e final
Exemplo
No diagrama de classes: Nome em itálico e
Exemplo
package carrointerface; interface VeicNovo{ double txjuros = 0.05; double entr = 0.30; double desc = 0.20;public double precoFabrica(); public double precoAVista();
public double prestacao(int npar); public double entrada();
} package carrointerface; interface VeicNovo{ double txjuros = 0.05; double entr = 0.30; double desc = 0.20;
public double precoFabrica(); public double precoAVista();
public double prestacao(int npar); public double entrada();
Exemplo
package carrointerface;class VeicBasico{
private String comb; private int cil;
public VeicBasico(String c,int ci) {comb=c; cil=ci;}
public String getComb() { return(comb); }
public int getCil() { return(cil); }
}
package carrointerface;
class VeicBasico{
private String comb; private int cil;
public VeicBasico(String c,int ci) {comb=c; cil=ci;}
public String getComb() { return(comb); }
public int getCil() { return(cil); }
Exemplo
package carrointerface;
class CarroPopular extends VeicBasico implements VeicNovo{ private double preco;
public CarroPopular(double p,String c,int cil){ super(c,cil); preco = p;
}
public double precoFabrica(){ return(preco); }
public double precoAVista(){ return(preco-(preco*desc)); } public double prestacao(int npar){
double saldo = preco - entrada(); double prest = saldo/npar;
for(int i=0; i<npar; i++)
prest = (prest+(prest*txjuros)); return(prest);
}
public double entrada(){ return(preco * entr); } }
package carrointerface;
class CarroPopular extends VeicBasico implements VeicNovo{ private double preco;
public CarroPopular(double p,String c,int cil){ super(c,cil); preco = p;
}
public double precoFabrica(){ return(preco); }
public double precoAVista(){ return(preco-(preco*desc)); } public double prestacao(int npar){
double saldo = preco - entrada(); double prest = saldo/npar;
for(int i=0; i<npar; i++)
prest = (prest+(prest*txjuros)); return(prest);
}
public double entrada(){ return(preco * entr); } }
Exemplo
package carrointerface;
public class TestaInterface{
public static void main(String args[]){ CarroPopular cp = new CarroPopular(14500,"Gasolina",1000); System.out.println("A vista:"+cp.precoAVista()); System.out.println("A prazo:"+cp.entrada()+"+ "+24+" X "+cp.prestacao(24)); } } package carrointerface;
public class TestaInterface{
public static void main(String args[]){ CarroPopular cp = new CarroPopular(14500,"Gasolina",1000); System.out.println("A vista:"+cp.precoAVista()); System.out.println("A prazo:"+cp.entrada()+"+ "+24+" X "+cp.prestacao(24)); } }
Em Java é possível armazenar um conjunto de valores,
primitivos ou objetos, utilizando variáveis compostas
homogêneas (vetores, matrizes, etc)
MOTIVAÇÃO
Mas e se quisermos:
Criar estruturas que aloquem dinamicamente espaço em
memória (aumentar ou diminuir o espaço em tempo de
execução)?
Criar estruturas de dados mais complexas com
disciplinas de acesso, através da implementação de tipos
abstratos de dados como listas, pilhas e filas?
MOTIVAÇÃO
Estas questões são tratadas, em um curso de
Computação, na disciplina Estrutura de Dados
Na linguagem de programação Java, estas estruturas
são oferecidas através do Java Collections
Framework
Criação de um
ArrayList
de objetos da classe
Aluno:
ArrayList<Aluno> alunos; alunos = new ArrayList<Aluno>();
Aluno a = new Aluno(); alunos.add(a);
Adiciona objetos à lista. Apenas Strings são permitidas
Declara uma lista de Strings. Foi escolhido um ArrayList para
implementação desta lista
import java.util.Collection; import java.util.List;
import java.util.ArrayList; public class Trapalhoes
{
public
static
void criarTrapalhoes() {ArrayList<String> trapalhoes = new ArrayList<String>(); trapalhoes.add( "Didi" );
trapalhoes.add( "Dedé" );
trapalhoes.add( "Mussum" ); trapalhoes.add( "Zacarias" );
*Obtém índice de um elemento *Altera um elemento em um índice
Itera pela
lista sem
usar índices
Remove
elementos: pelo
índice, pelo
valor
Itera pelos
objetos da lista
usando índices
for ( int i=0; i<trapalhoes.size(); i++ ) { String str = trapalhoes.get(i); System.out.println( str ); } trapalhoes.remove(3); trapalhoes.remove( "Mussum" ); System.out.println( "=================" ); for ( String s: trapalhoes )
System.out.println( s );
int indice = trapalhoes.indexOf( "Didi" ); trapalhoes.set( indice, "Chaves" );
System.out.println( "=======================" ); for ( String s: trapalhoes )
System.out.println( s );
} //Fim do método criarTrapalhoes()
public
static
void main( String args[] ) {criarTrapalhoes(); }
}
Exceções
Mecanismo eficiente de
comunicação
entre
programadores e utilizadores de classes, para lidar com
situações especiais
Lançando uma exceção
Exceção
é um
objeto
que sinaliza que uma condição
excepcional ocorreu, representando detalhes de uma
falha de execução
Objeto precisa ser criado com new e lançado com throw
IllegalArgumentException e = new IllegalArgumentException(“Erro”);
throw e;
Ao lançar uma exceção, a classe comunica que não foi
capaz de realizar a operação solicitada com sucesso
Lançando uma exceção
Exemplo:
public void atualizaTelefone(String nome, String novoTelefone){
Contato c = contatos.get(nome); if(c == null)
throw new NullPointerException(“Contato inexistente”);
c.setTelefone(novoTelefone); }
Sintaxe
:
throw new
Tipo_de_Exceção(“string de diagnóstico
Capturando e tratando exceção
Capturar uma exceção significa providenciar um trecho de
código que detecte o lançamento de uma exceção e
dispare ações correspondentes
Isso é feito pelo bloco try … catch
Sintaxe
:
try {
// chamadas de métodos que podem lançar exceções }
catch (Exception e) {
// ações correspondentes à detecção de uma
determinada exceção
Capturando e tratando exceção
Exemplo:
try {
FileWriter stream = new FileWriter(“c:\teste.txt”);
PrintWriter out = new PrintWriter(stream);
out.println(“oi”); out.close();
}
catch ( IOException erro ) {
System.out.println ("Erro na escrita dos dados" );
}
Podem lançar
exceções
Há várias
fontes (entrada)
de onde se deseja ler, ou
destinos
(saída)
para onde se deseja gravar ou enviar dados:
Arquivos
Conexões via socket com outros programas
Memória
Teclado, tela, impressora, mouse, etc
Há várias formas diferentes de ler/escrever dados:
Sequencialmente/aleatoriamente
Como bytes, como caracteres
Linha por linha, palavra por palavra, etc
ARQUIVOS
Como oferecer estes serviços em
Java??
ESCRITA/GRAVAÇÃO EM ARQUIVOS TEXTO
Compreende a criação do arquivo, o armazenamento dos dados, e
o fechamento do arquivo
FileWriter: Estabele a conexão com o arquivo. Usado para a
saída, para um arquivo, baseada em caracteres
FileWriter arq = new FileWriter( nomeArq );
PrintWriter: Para escrevermos Strings no arquivo, precisamos
de um objeto PrintWriter associado ao FileWriter
PrintWriter out = new PrintWriter( arq );
Podemos então usar os métodos print() e println() da
classe PrintWriter
Devemos implementar o código dentro de um bloco try/catch,
pois exceções podem ser geradas (IOException)
ESCRITA SEQUENCIAL EM ARQUIVOS TEXTO
BufferredWriter: Esta classe permite uma saída buferizada
Uma operação de saída não grava imediatamente os dados no
arquivo
Com o método flush(), de tempos em tempos uma quantidade
de dados é enviada para o arquivo
LEITURA SEQUENCIAL EM ARQUIVOS TEXTO
Consiste na recuperação das informações armazenadas em um
arquivo, para serem utilizadas por determinado programa
FileReader: Estabele a conexão com o arquivo. Uma operação
de entrada lê um caracter. Ou seja, trabalha com um caracter por
vez
FileReader ent = new FileReader( nomeArq );
BufferedReader: Entrada buferizada. Uma operação de entrada
lê vários caracteres de uma única vez
BufferedReader br = new BufferedReader (ent);
Método utilizado para leitura: br.readLine()
UsarArquivo.java
public class UsarArquivo {
public static void main( String[] args ) {
String nome[]=new String [3]; int idade[]=new int [3]; double nota[] = new double [3];
nome[0] = "José da Silva"; nome[1] = "Márcia Bastos"; nome[2] = "Carla Pereira"; idade[0] = 23;
idade[1] = 20; idade[2] = 18;
nota[0] = 7.5; nota[1] = 7; nota[2] = 8.5;
GerenciamentoArquivos gerente = new GerenciamentoArquivos(); gerente.escrita( "teste.dat", nome, idade, nota );
gerente.leitura( "teste.dat" ); }
GerenciamentoArquivos.java 1/3
import java.io.*;
public class GerenciamentoArquivos {
public void escrita ( String nomeArq, String[] vet1, int[] vet2, double[] vet3 )
{
try {
FileWriter arq = new FileWriter( nomeArq ); PrintWriter out = new PrintWriter( arq ); for ( int i=0; i<vet1.length; i++ )
{
String linha = vet1[i] + ":" + vet2[i] + ":" + vet3[i]; out.println( linha );
}
out.close(); }
catch ( IOException erro )
{ System.out.println ( "Erro na escrita dos dados" ); } } //fim do método escrita()
GerenciamentoArquivos.java 2/3
public void leitura ( String nomeArq ) {
try {
FileReader ent = new FileReader( nomeArq );
BufferedReader br = new BufferedReader ( ent ); String linha; String[] campos = null;
while ( (linha = br.readLine()) != null ) {
campos = linha.split( ":" ); String nome = campos[ 0 ];
int idade = Integer.parseInt( ( campos[1]) ); double nota = Double.parseDouble(
campos[2].replace( ",", "." ) );
System.out.println( "Nome=" + nome + " Idade=" + idade + " Nota=" + nota );
}
br.close(); }
GerenciamentoArquivos.java 3/3
catch ( IOException erro ) {
System.out.println ( "Erro na leitura dos dados" ); }
} // Fim do método leitura() } // Fim da classe
PERSISTÊNCIA DE DADOS: SERIALIZAÇÃO
Como permitir a
serialização/deserialização em Java???
Fazendo os objetos implementarem a interface
Serializable
Serializable não tem métodos. Serve apenas para
indicar que os atributos destes objetos podem ser
serializados e deserializados
ESCRITA DE OBJETOS - SERIALIZAÇÃO
Passos para gravar/escrever um objeto serializado em um arquivo
Criar um objeto FileOutputStream:
FileOutputStream arq = new
FileOutputStream(nomeArq);
Criar um objeto ObjectOutputStream:
ObjectOutputStream os = new
ObjectOutputStream( arq );
Gravar o objeto:
os.writeObject ( objeto );
Fechar o objeto ObjectOutputStream:
os.close();
LEITURA DE OBJETOS - DESERIALIZAÇÃO
Restauração do estado de um objeto
Criar um objeto FileInputStream:
FileInputStream arq = new
FileInputStream(nomeArq);
Criar um objeto ObjectInputStream:
ObjectInputStream is = new
ObjectInputStream(arq);
Ler o objeto:
Medicamento m=(Medicamento) is.readObject();
Trabalhar com o objeto:
System.out.print( "Nome: " + m.getNome() );
Fechar o objeto ObjectOutputStream:
Medicamento.java 1/2
import java.io.Serializable;
public class Medicamento
implements Serializable
{String nome; double preco; public Medicamento ()
{ }
public Medicamento (String novoNome, double novoPreco) {
this
.nome = novoNome; this.preco = novoPreco; }public void setNome(String novoNome) {
this.nome = novoNome; }
Medicamento.java 2/2
public void setPreco(double novoPreco) {
this.preco = novoPreco; }
public String getNome() { return this.nome;
}
public double getPreco() { return this.preco;
}
public void escreverMedicamento() {
System.out.println("Nome" + this.nome); System.out.println("Preco" + this.preco); }
TestaFarmaciaSerializacao.java 1/2
public class TestaFarmaciaSerializacao {
public static void main( String[] args ) {
Farmacia ufu = new Farmacia(); /* cadastro de medicamentos */
Medicamento m = new Medicamento("a", 5.6); ufu.cadastraMedicamento(m); m = new Medicamento("b", 15.6); ufu.cadastraMedicamento(m); m = new Medicamento("c", 25.6); ufu.cadastraMedicamento(m); m = new Medicamento("d", 35.6); ufu.cadastraMedicamento(m); m = new Medicamento("e", 3.6); ufu.cadastraMedicamento(m);
TestaFarmaciaSerializacao.java 2/2
//Serializa os objetos ufu.escreverMedicamentos( "medicamentos.dat" ); //Deserializa os objetos ufu.lerMedicamentos( "medicamentos.dat" ); } }Farmacia.java 1/5
import java.io.*;
public class Farmacia {
Medicamento lista[] = new Medicamento[100]; int estoque = 0;
public void cadastraMedicamento (Medicamento m) {
lista[estoque] = m; estoque++;
}
public void cadastrMedicamento (String nome, double preco)
{
Medicamento m = new Medicamento(nome, preco); lista[estoque] = m; estoque++;
Farmacia.java 2/5
//OUTROS MÉTODOS
public void escreverMedicamentos() {
for (int i = 0; i<estoque; i++){
lista[i].escreverMedicamento(); }
}
Farmacia.java 3/5
public void escreverMedicamentos( String nomeArq ) {
try {
FileOutputStream arq=new FileOutputStream(nomeArq); ObjectOutputStream os=new ObjectOutputStream(arq); for ( int i=0; i<estoque; i++ )
os.writeObject( lista[i] ); os.close(); arq.close();
}
catch ( IOException erro ) {
System.out.println ( "Ocorreu um erro na escrita dos dados" + erro );
}
Farmacia.java 4/5
public void lerMedicamentos( String nomeArq ) {
try {
FileInputStream arq=new FileInputStream(nomeArq); ObjectInputStream is=new ObjectInputStream(arq); for ( int i=0; i<estoque; i++ )
{
Medicamento m = (Medicamento) is.readObject(); System.out.print( "Nome: " + m.getNome() );
System.out.println( " Preco: " + m.getPreco() ); } is.close(); arq.close(); }
Farmacia.java 5/5
catch ( IOException erro ) {
System.out.println ( "Ocorreu um erro na escrita dos dados: " + erro );
}
catch ( ClassNotFoundException erro ) {
System.out.println ( "Ocorreu um erro de leitura no
arquivo: " + erro ); }
} //Fim do método lerMedicamentos() } //Fim da classe