método - BCC Unifal-MG

Propaganda
Programação Orientada a Objetos com Java
Módulo 06
Desenho de Classes
Última Atualização: 13/06/2010
1
Programação Orientada a Objetos com Java
Objetivos
• Definir os conceitos de herança, polimorfismo, sobrecarga
(overloading), sobreescrita(overriding) e invocação virtual
de métodos.
• Utilizar os modificadores de acesso protected e “packagefriendly”.
• Descrever os conceitos de sobrecarga de construtores e
métodos.
2
Programação Orientada a Objetos com Java
Objetivos (Cont.)
• Descrever a operação de construção e iniciação de um
objeto.
•Discutir o conceito de AutoBoxing introduzido no Java 5
3
Programação Orientada a Objetos com Java
Herança
A classe Empregado:
public class Empregado {
private Data dataNascimento;
private String primeiroNome;
private String ultimoNome;
public String getDetalhes ( ) { ...}
}
4
Programação Orientada a Objetos com Java
Herança(Cont.)
A classe Gerente:
public class Gerente {
private Data dataNascimento;
private String departamento;
private String primeiroNome;
private String ultimoNome;
public String getDetalhes ( ) { ...}
}
5
Programação Orientada a Objetos com Java
Herança(Cont.)
public class Empregado {
private Data dataNascimento;
private String primeiroNome;
private String ultimoNome;
public String getDetalhes ( ) { ...}
}
public class Gerente extends Empregado {
private String departamento;
}
6
Programação Orientada a Objetos com Java
Herança Simples
• Quando uma classe herda apenas de uma outra classe,
obtemos uma herança simples.
• Herança Múltipla é realizada através do conceito de
Interfaces (próximo módulo).
• Sintaxe de uma classe Java:
<modificador de acesso> class <nome> [extends <superclasse>]{
<declarações>*
}
7
Programação Orientada a Objetos com Java
Herança Simples(Cont.)
8
Programação Orientada a Objetos com Java
Controle de Acesso
Modificador
Classe
Pacote
Subclasse
private
Sim
default
Sim
Sim
protected
Sim
Sim
Sim*
public
Sim
Sim
Sim
Aplicação
Sim
* Para uma subclasse fora do pacote, o membro protected somente pode ser acessado via herança.
Se tentarmos acessar o membro via uma referência da superclasse, teremos um erro de
compilação!!!
9
Programação Orientada a Objetos com Java
Sobreescrita de Métodos
• Uma subclasse pode modificar o comportamento herdado
da super classe.
• Uma subclasse pode criar um método com uma
funcionalidade diferente da super classe, entretanto, com o
mesmo:
•
•
•
Nome
Tipo de Retorno
Lista de Argumentos
10
Programação Orientada a Objetos com Java
Sobreescrita de Métodos
public class Empregado {
protected String primeiroNome;
protected double salario;
protected Data dataNascimento;
public String getDetalhes() {
return “Primeiro Nome..:” + primeiroNome\n”
+ “Salario..:”+ salario + “\n”
)
}
public class Gerente extends Empregado {
private String departamento;
public String getDetalhes() {
return “Primeiro Nome..:” + primeiroNome\n”
+ “Salario..:”+ salario + “\n”
+ “Departamento..:” + departamento;
}}
11
Programação Orientada a Objetos com Java
A Palavra Reservada super
• super é utilizada em uma classe para referenciar a
superclasse.
• super é utilizada para referenciar membros da superclasse,
mais especificamente, atributos, construtores e métodos.
• O comportamento (método) invocado não necessariamente
necessita estar na superclasse; ele pode estar em outro local
dentro da hierarquia.
12
Programação Orientada a Objetos com Java
A Palavra Reservada super
public class Empregado {
private String nome;
private double salario;
private String dataNascimento;
public String getDetalhes() {
return "Nome: " + nome + "\n Salário: " + salario;
}
}
public class Gerente extends Empregado {
private String departamento;
public String getDetails() {
// chama o método getDetalhes( ) presente na superclasse
return super.getDetalhes() +
"\n Departamento:" + departamento;
}}
13
Programação Orientada a Objetos com Java
Polimorfismo
• Polimorfismo é a capacidade de se ter várias formas
distintas; por exemplo, a classe Gerente tem acesso a
métodos da classe Empregado.
• Um objeto possui apenas uma forma.
• Uma variável de referência pode referenciar objetos que
possuem formas totalmente distintas.
14
Programação Orientada a Objetos com Java
Polimorfismo(Cont.)
Empregado empregado = new Gerente(); // OK
/*
Tentativa ilegal de atribuir um atributo de gerente. A variável é declarada como
sendo do tipo Empregado, embora o objeto Gerente possua este atributo.
*/
empregado.departamento = “Vendas”;
15
Programação Orientada a Objetos com Java
Invocação Virtual de Método
• Invocação Virtual de Método:
Empregado e = new Gerente();
e.getDetalhes();
• Tipo em tempo de Compilação e tipo em tempo de
execução (Late Binding)
16
Programação Orientada a Objetos com Java
Regras sobre Métodos
Sobreescritos
• Deve ter um tipo de retorno que seja idêntico ou subclasse
do tipo definido no método que está sendo sobreescrito
(Retorno co-variante, introduzido no Java 5).
• Não pode ser menos acessível que o método que ele
sobrescreve.
17
Programação Orientada a Objetos com Java
Regras sobre Sobrescrita de
Métodos(Cont.)
public class Pai {
public void fazAlgo() { }
}
public class Filha extends Pai {
private void fazAlgo() { }
}
public class UsaAmbas {
public void fazOutraCoisa() {
Pai p1 = new Pai();
Pai p2 = new Filha();
p1.fazAlgo();
p2.fazAlgo(); //Erro!!
}}
18
Programação Orientada a Objetos com Java
Coleções Heterogêneas
• Coleções de objetos com o mesmo tipo são chamadas de
coleções homogêneas.
Data[] datas = new Data[2];
datas[0] = new Data(22, 12, 1964);
datas[1] = new Data(22, 7, 1964);
• Coleções de objetos de tipos diferentes são conhecidas
como coleções heterogêneas.
Empregado [] funcionarios = new Empregado[1024];
funcionarios[0] = new Gerente();
funcionarios[1] = new Empregado();
funcionarios[2] = new Engenheiro();
19
Programação Orientada a Objetos com Java
Argumentos Polimórficos
Devido ao fato de Gerente ser um Empregado:
// Na classe Empregado
public TaxaJuros encontraTaxaJuros(Empregado e) {}
// Enquanto isso, em algum ponto da aplicação
Gerente m = new Gerente();
...
...
TaxaJuros t = encontraTaxaJuros(m);
20
Programação Orientada a Objetos com Java
O Operador instanceof
public class Empregado extends Object
public class Gerente extends Empregado
public class Engenheiro extends Empregado
--------------------------------------- -
public void fazAlgo(Empregado e) {
if (e instanceof Gerente) {
// Processamento de Gerente
} else if (e instanceof Engenheiro) {
// Processamento de Engenheiro
} else {
// Processamento de outro tipo de Empregado
}
}
21
Programação Orientada a Objetos com Java
Conversão (Casting) de Objetos
• Use instanceof para testar o tipo de um objeto.
• Restaure toda a funcionalidade de um objeto através de um
casting (conversão de tipos).
• Confira o casting utilizando as seguintes recomendações:
• Conversões
para cima na hierarquia são feitas
implicitamente.
• Conversões para baixo devem ser feitas para uma subclasse
e sua checagem é feita pelo compilador.
• O tipo do objeto é conferido em tempo de execução.
22
Programação Orientada a Objetos com Java
Sobrecarga de Métodos
• Utilizado da seguinte maneira:
public void println(int i)
public void println(float f)
public void println(String s)
• A lista de argumentos deve ser diferente.
• O tipo de retorno pode ser diferente
23
Programação Orientada a Objetos com Java
Sobrecarga de Construtores
• Semelhante a métodos, podemos fazer a sobrecarga de
construtores.
• Exemplo:
public Empregado(String nome, double salario, String data)
public Empregado(String nome, double salario)
public Empregado(String nome, String data)
• A lista de argumentos deve ser diferente.
• Você pode usar a referência this na primeira linha de um
construtor para chamar outro construtor.
24
Programação Orientada a Objetos com Java
Sobrecarga de Construtores
1 public class Empregado {
2
3
private String nome;
4
private double salario;
5
private String dataNascimento;
6
7
public Empregado(String nome, double salario, String dataNascimento) {
8
this.nome = nome;
9
this.salario = salario;
10
this.dataNascimento = dataNascimento;
11 }
12 public Empregado(String nome, double salario) {
13
this(nome, salario, null);
14 }
15 public Empregado(String nome, String dataNascimento) {
16
this(nome, 0.0, dataNascimento);
17 }
18 public Empregado(String nome) {
19
this(nome, salario);
20 }
21 }
25
Programação Orientada a Objetos com Java
Construtores Não São Herdados
• Uma subclasse herda todos os métodos e variáveis public
ou protected da superclasse.
• Uma subclasse NÃO herda o construtor da superclasse.
• Existem duas maneiras de se incluir um construtor:
•
•
Utilizando o construtor default,
Escrever explicitamente um ou mais construtores.
26
Programação Orientada a Objetos com Java
Chamando Construtores da
Superclasse
• Para se chamar um construtor da superclasse, devemos
inserir uma chamada super na primeira linha do construtor.
• Você pode chamar um construtor específico da superclasse
através dos argumentos utilizados na chamada super
27
Programação Orientada a Objetos com Java
Chamando Construtores da
Superclasse (Cont.)
• Se não houver uma chamada explícita this ou super no
construtor, então o compilador adiciona uma chamada
implícita para super(), que por sua vez, chama o construtor
da superclasse sem argumentos (que pode ser o construtor
default).
• Se a superclasse definir construtores, mas não fornecer um
construtor sem argumentos, então uma mensagem de erro é
gerada.
28
Programação Orientada a Objetos com Java
Chamando Construtores da
Superclasse
1 public class Empregado {
2
3
private String nome;
4
private double salario;
5
private String dataNascimento;
6
7
public Empregado(String nome, double salario, String dataNascimento) {
8
this.nome = nome;
9
this.salario = salario;
10
this.dataNascimento = dataNascimento;
11 }
12 public Empregado(String nome, double salario) {
13
this(nome, salario, null);
14 }
15 public Empregado(String nome, String dataNascimento) {
16
this(nome, 0.0, dataNascimento);
17 }
18 public Empregado(String nome) {
19
this(nome, 0.0);
20 } }
29
Programação Orientada a Objetos com Java
Chamando Construtores da
Superclasse(Cont.)
1 public class Gerente extends Empregado {
2 private String departamento;
3
4 public Gerente(String nome,double salario, String dept) {
5
super(nome, salario);
6
departamento = dept;
7 }
8 public Gerente(String n, String dept) {
9
super(nome);
10 departamento = dept;
11 }
12 public Gerente(String dept) { // erro: ausência de super() explícito
13
departamento = dept;
14 }
15 }
30
Programação Orientada a Objetos e Linguagem de Programação Java
Construindo e Iniciando Objetos:
Breve Revisão
• A memória é alocada e iniciação “default” ocorre.
• A iniciação das variáveis de instância utiliza estes passos
recursivamente:
1. “casa” os parâmetros do construtor.
2. Se houver um this(), chama recursivamente, e vá para o passo 5.
3. Chama super recursivamente, de forma implícita ou explícita, exceto para
Object.
4. Executa iniciadores explícitos das variáveis de instância.
5. Executa o bloco do construtor.
31
Programação Orientada a Objetos e Linguagem de Programação Java
Exemplo de Construtor e Iniciação
public class Object {
public Object() {}
}
public class Empregado extends Object {
private String nome;
private double salario = 1500.00;
private String dataNascimento;
public Empregado(String n, String dataNascimento) {
// super() implícito
nome = n;
this.dataNascimento = dataNascimento;
}
public Empregado(String n) {
this(n, null);
}
}
public class Gerente extends Empregado {
private String departamento;
public Gerente(String n, String d) {
super(n);
departamento = d;
}}
32
Programação Orientada a Objetos e Linguagem de Programação Java
Exemplo de Construtor e Iniciação
Exemplo supondo a construção new Gerente(“Joe Smith”, “Vendas”)
0 Iniciação básica
0.1 Alocação de memória para o objeto Gerente
0.2 Inicia todas as variáveis de instância com seus valores default (0 ou null)
1 Chama o construtor: Gerente("Joe Smith", "Vendas")
1.1 “Casa” os parâmetros do construtor: n="Joe Smith", d="Vendas"
1.2 Não há uma chamada explícita para this()
1.3 Chama super(n) para Empregado(String n)
1.3.1 “Casa” os parâmetros do construtor: n="Joe Smith"
1.3.2 Chama this(n, null) para Empregado(String n , String dataNascimento)
1.3.2.1 “Casa” parâmetros do construtor: n="Joe Smith", dataNascimento=null
1.3.2.2 Não há uma chamada explícita para this()
1.3.2.3 Chama super() para Object()
1.3.2.3.1 Nenhum “casamento” necessário
1.3.2.3.2 Não há chamada this()
1.3.2.3.3 Não há chamada super() (Object é a raiz)
1.3.2.3.4 Não existe iniciação explícita de variáveis para Object
1.3.2.3.5 Não há chamada de método
1.3.2.4 Inicia explicitamente variáveis de Empregado: salario=1500.00;
1.3.2.5 Executa o corpo do construtor: nome="Joe Smith"; dataNascimento=null;
1.3.3 - 1.3.4 passos não necessários
1.3.5 Executa o corpo do construtor: Não há instruções em Empregado(String)
1.4 Não há iniciadores explícitos para Gerente
1.5 Executa o corpo do construtor: departamento="Vendas".
33
Programação Orientada a Objetos com Java
A Classe Object
• A classe Object é a super classe de todas as classes em
Java.
• Uma declaração de classe sem a cláusula extends utiliza,
implicitamente, a instrução “ extends Object ”
public class Empregado {
...
}
é equivalente a:
public class Empregado extends Object {
...
}
34
Programação Orientada a Objetos com Java
O Operador == Comparado com o
Método equals
• O operador == determina se duas referências são idênticas
(ou seja, referem ao mesmo objeto).
• O método equals determina se objetos são “iguais” em
conteúdo, mas não necessariamente idênticos.
• A implementação do método equals em Object utiliza o
operador ==.
35
Programação Orientada a Objetos com Java
O Operador == Comparado com o
Método equals(Cont.)
• Classes definidas pelo programador podem fazer a
sobreescrita do método equals(Object o) para implementar
um teste de igualdade-domínio.
• Nota: Devemos fazer a sobreescrita do método hashCode()
se fizermos a sobreescrita do método equals(Object o).
• Maiores detalhes no módulo sobre Coleções Java
36
Programação Orientada a Objetos com Java
Exemplo: equals
1 public class Data{
2 private int dia;
3 private int mes;
4 private int ano;
5
6 public Data(int dia, int mes, int ano) {
7
this.dia = dia;
8
this.mes = mes;
9
this.ano = ano;
10 }
11
12 public boolean equals(Object o) {
13 boolean resultado = false;
14
if ( (o != null) && (o instanceof Data) ) {
15
Data d = (Data) o;
16
if ((dia == d.dia) && (mes == d.mes)
17
&& (ano == d.ano) ) {
18
resultado = true;
19
}
20
}
21
return resultado;
22 }
23
24 public int hashCode() {
25 return (dia ^ mes ^ ano);
26 }
27 }
37
Programação Orientada a Objetos com Java
Exemplo: equals
1 class TesteEquals {
2 public static void main(String[] args) {
3
Data data1 = new Data(14, 3, 1976);
4
Data data2 = new Data(14, 3, 1976);
5
6
if (data1 == data2 ) {
7
System.out.println("data1 idêntica a data2");
8
} else {
9
System.out.println("data1 não é identica a data2");
10
}
11
12
if (data1.equals(data2) ) {
13
System.out.println("data1 é igual a data2");
14
} else {
15
System.out.println("data1 não é igual a data2");
16
}
17
18
System.out.println("atribui data2 = data1;");
19
data2 = data1;
20
21
if (data1 == data2 ) {
22
System.out.println("data1 é idêntica a data2");
23
} else {
24
System.out.println("data1 não é identica a data2");
25
}
26 }
27 }
Gera a saída:
data1 não é idêntica a data2
data1 é igual a data2
Atribui data2 = data1;
data1 é idêntica a data2.
38
Programação Orientada a Objetos com Java
O Método toString()
• Converte um objeto em uma String.
• Usado durante concatenação de strings.
• Fazemos a sobreescrita deste método para fornecer informação
sobre um objeto definido pelo programador em um formato
legível.
• Tipos primitivos são convertidos em String utilizando o método
estático toString() da classe empacotadora (wrapper class).
39
Programação Orientada a Objetos com Java
Classes Empacotadoras “Wrapper “
• Tratam elementos de tipos primitivos como objetos:
Tipo Primitivo
Classe Empacotadora
boolean
Boolean
byte
Byte
short
Short
int
Integer
long
Long
float
Float
double
Double
char
Character
40
Programação Orientada a Objetos com Java
Classes Empacotadoras
• Pré Java 5
// Definindo um tipo primitivo
int primitivoInt = 500;
// Empacotando o tipo primitivo definido acima
Integer empacotandoInt = new Integer(primitivoInt);
// Convertendo novamente para primitivo
int primitivo2 = empacotandoInt.intValue();
• Pós Java 5
• Autoboxing
• Elimina o trabalho do programador de ter que fazer o encapulamento/desencapsulamento de um
tipo primitivo com sua respectiva classe empacotadora.
41
Programação Orientada a Objetos com Java
Autoboxing e Unboxing
42
Programação Orientada a Objetos com Java
AutoBoxing e UnBoxing - Agenda
Convertendo Tipos Primitivos para Classes Empacotadoras – Wrapper
Classes
Convertendo Classes Empacotadoras para Tipos Primitivos
Incrementando e Decrementando Classes Empacotadoras
Valores Boolean versus boolean
Estruturas Condicionais e UnBoxing
Instruções de Controle e Unboxing
Resolução na Sobrecarga de Métodos
43
Programação Orientada a Objetos com Java
Autoboxing/Unboxing de tipos
Primitivos
Problema: (pré-Java 5):
1. Conversão entre tipos primitivos e tipos wrapper (e vice-versa)
2. Você precisa converter manualmente um tipo primitivo para um tipo
wrapper antes de adicioná-lo na coleção
int i = 22;
Integer[] b = new Integer[1];
b[0] = new Integer(i);
44
Programação Orientada a Objetos com Java
Autoboxing/Unboxing de tipos
Primitivos
Solução: Deixe o compilador fazer isto
Byte byteObj = 22; // Conversão Autoboxing
int i = byteObj // Conversão Unboxing
Integer[] lista = new Integer[1];
lista[0] = 22; // Conversão Autoboxing
45
Programação Orientada a Objetos com Java
Incrementando e Decrementando
Classes Empacotadoras
Podemos utilizar as operações ++ e - - com classes empacotadoras
Integer contador = 1;
while (true) {
System.out.println(“Iteração..: “ + contador++);
if (contador > 1000) {
break;
}
}
A variável contador é tratada com um tipo primitivo int neste código
46
Programação Orientada a Objetos com Java
Incrementando e Decrementando
Classes Empacotadoras (cont.)
Pontos importantes neste código:
contador++
■ lembre-se que contador é um Integer. Nessa linha foi feito um
Unboxing para o tipo int que é o tipo necessário ao operador ++ (o
operador ++ não foi alterado para funcionar com Unboxing)
■ Após unboxing do valor, o incremento é feito e o novo valor é
armazenado novamente em contador através de uma operação
Boxing.
■ O processo de unboxing também é demonstrado na linha contador
> 1000
47
Programação Orientada a Objetos com Java
Valores Boolean versus boolean
Operadores booleanos como !, ||, && são úteis para valores Boolean.
Sempre que tivermos uma expressão que usa !, ||, ou && qualquer valor
Boolean é convertido em tipo primitivo e avaliado adequadamente
Boolean caso1 = true;
Boolean caso2 = true;
boolean caso3 = false;
Boolean resultado = (caso1 || caso2) && caso3;
Neste código o resultado da expressão, é encapsulado dentro da variável
resultado (AutoBoxing)
48
Programação Orientada a Objetos com Java
Estruturas Condicionais e UnBoxing
O conceito de boxing/unboxing afeta, tornando mais flexível, a utilização do
operador ternário
expressao ? expressao1 : expressao2;
Em versões anteriores ao Tiger o operador ternário necessitava que seus
operandos fossem de tipos compatíveis ou que um pudesse ser associado a
outro (ex: int e float).
No tiger, os operandos do operador ternário podem ser praticamente de
qualquer tipo.
49
Programação Orientada a Objetos com Java
Estruturas Condicionais e UnBoxing
Exemplo:
Boolean estaChegando = false;
Boolean estaAtrasado = true;
System.out.println(estaChegando? “chegou no horário” : “Você está
atrasado”);
O operador ternário no tiger permite o casting automático de referência para
a superclasse comum aos dois operandos.
Exemplo (Funciona somente a partir do JavaSE 5, Tiger) :
String s = olá;
StringBuffer sb = new StringBuffer(“mundo”);
boolean eMutavel = true;
CharSequence c = eMutavel? sb : s; // CharSequence é superclasse de
// StringBuffer e String
50
Programação Orientada a Objetos com Java
Estruturas Condicionais e UnBoxing
(Cont.)
O código no slide anterior gera um erro em versão anteriores ao Java 5 já que
String e StringBuffer não podem ser associadas uma a outra.
Este código poderá funcionar em versões anteriores ao Java 5 se o
programador fizer algumas conversões:
String s = olá;
StringBuffer bf = new StringBuffer(“mundo”);
boolean eMutavel = true;
CharSequence c = eMutavel? (CharSequence)sb : (CharSequence)s;
Repare que poderíamos utilizar Object em vez de CharSequence no
exemplo acima.
51
Programação Orientada a Objetos com Java
Estruturas de Controle e UnBoxing
As estruturas de controle if/else, while, do são afetadas pelo conceito de
boxing/unboxing
Integer pessoasNaSala = 0;
int capacidadeMaxima = 100;
boolean horaDePartir = false;
Boolean chegando = true;
while (pessoasNaSala < capacidadeMaxima) {
if (chegando) {
System.out.println("Bom ver você.");
pessoasNaSala++;
} else {
pessoasNaSala--;
}
if (horaDePartir) {
do {
System.out.printf("Número de pessoas na sala ” + pessoasNaSala);
pessoasNaSala--;
} while (pessoasNaSala > 0);
} }
52
Programação Orientada a Objetos com Java
Estruturas de Controle e UnBoxing
(Cont.)
Outra estrutura de controle beneficiada é o switch
Em Tiger a instrução switch funciona com:
■ byte, short, int, char, Byte, Short, Integer, Character e enum
53
Programação Orientada a Objetos com Java
Resolução na Sobrecarga de Métodos
Resolução de métodos é o processo pelo qual o compilador Java determina
qual método é invocado.
Boxing e Unboxing afetam este processo.
Exemplo:
public void fazAlgo(double num)
public void fazAlgo(Integer num)
Invocando fazAlgo() :
...
int foo = 1;
fazAlgo(foo); // Qual método é chamado ???
...
54
Programação Orientada a Objetos com Java
Resolução na Sobrecarga de Métodos
(Cont.)
Antes do Tiger isso era fácil:
O tipo int era convertido em double e o método fazAlgo(double num) era
invocado
A primeira vista pode parecer que, com o Tiger, o tipo int é encapsulado em
um Integer e faz Algo(Integer num) é invocado
ISSO NÃO ACONTECE !!!!
Resolução de métodos em Tiger sempre selecionará o mesmo método que
seria invocado utilizando Java 4 (Compatibilidade retroativa)
55
Programação Orientada a Objetos com Java
Perguntas?
56
Download