Aula 11 - manipulação de ref, polimorfismo e lig. din

32
1 Aula 11 Manipulação de Referências, Polimorfismo e Ligação Dinâmica Programação Orientada a Objetos Rafael Braga

Transcript of Aula 11 - manipulação de ref, polimorfismo e lig. din

Page 1: Aula 11 - manipulação de ref, polimorfismo e lig. din

1

Aula 11 – Manipulação de Referências,

Polimorfismo e Ligação Dinâmica

Programação

Orientada a Objetos

Rafael Braga

Page 2: Aula 11 - manipulação de ref, polimorfismo e lig. din

2

• De maneira geral, o tratamento dado em Java para

conversões de tipo para referências a objetos é análogo

ao que acontece nas conversões de tipos primitivos.

• Conversões de tipo (classe) para referências a objetos

podem ocorrer:

– implicitamente, em atribuições e passagem de parâmetros, ou

– através de casting explícito.

• Conversões de tipos mais específicos para tipos mais

gerais (upcasting) são permitidas.

• O contrário, conversões de tipos mais gerais para tipos

mais específicos (downcasting) exigem casting

explícito. Isto vale para a hierarquia completa de

herança, incluindo classes e interfaces.

Manipulando Referências

Page 3: Aula 11 - manipulação de ref, polimorfismo e lig. din

3

• Regras de Conversão para Operações com

Variáveis de Referência

1. Operação de Atribuição:

TipoDeOrigem origRef;

TipoDeDestino destRef = origRef;

2. Operação de Passagem de Parâmetro:

TipoDeOrigem origRef;

enviarParam( origRef );

...

void enviarParam( TipoDeDestino destRef )

{ ... }

Manipulando Referências

Page 4: Aula 11 - manipulação de ref, polimorfismo e lig. din

4

• Como já foi visto em seções anteriores, a

passagem de parâmetros de tipos primitivos

em Java é feita por valor, ou seja, uma cópia do

valor original é feita.

• Isso significa que modificações no parâmetro

formal não são refletidas no parâmetro real.

• Para arrays, uma cópia da referência para o

array é passada.

• Para objetos, uma cópia da referência ao

objeto é passada, e não uma cópia do objeto.

Passagem de Parâmetros

Page 5: Aula 11 - manipulação de ref, polimorfismo e lig. din

5

• Para arrays, uma cópia da referência para o array é passada, assim, as mudanças no seus elementos dentro de um método, se refletem no lugar onde o método foi chamado. public static void somar(int[] x)

{

x[2] = x[1] + x[0];

}

public static void main (String args[]) {

int[] a = new int[3];

a[0] = 1;

a[1] = 10;

a[2] = 20;

System.out.println(“antes >”+ a[2]);

somar(a);

System.out.println(“depois >”+ a[2]);

}

antes >20

depois >11

Passagem de Parâmetros com Arrays

Page 6: Aula 11 - manipulação de ref, polimorfismo e lig. din

6

• Graficamente...

public static void somar(int[] x)

{

x[2] = x[1] + x[0];

}

...

somar(a);

Passagem de Parâmetros com Arrays

1 10 20

a

x

Page 7: Aula 11 - manipulação de ref, polimorfismo e lig. din

7

hoje 0x852ef8b

dia = 11;

mes = 05; ano = 2004;

Passagem de Parâmetros com Referências

• Relembrando funcionamento das referências... Data hoje;

hoje = new Data();

hoje.setDia(11);

hoje.setMes(02);

hoje.setAno(2004);

Data outroDia = hoje;

outroDia.setMes(05);

outroDia

referências objeto

Page 8: Aula 11 - manipulação de ref, polimorfismo e lig. din

8

• Esse “fenômeno” é conhecido como aliasing.

• Apesar da passagem por parâmetros em Java ser

por valor, pode-se ter aliasing quando um objeto é

passado como parâmetro, assim como acontece

na atribuição de referências.

• É sempre a referência (ponteiro) de um objeto que

é passada como parâmetro e não o objeto em si.

• O parâmetro formal passa a ser uma referência

para a mesma instância do objeto passado, logo,

qualquer mudança nos valores do objeto se reflete

no lugar onde o método foi chamado.

Passagem de Parâmetros com Referências

Page 9: Aula 11 - manipulação de ref, polimorfismo e lig. din

9

• Exemplo public static void main( String args[] ) {

Data hoje;

hoje = new Data();

funcao(hoje);

System.out.println( hoje.getMes() ); // 10

}

static void funcao( Data umaData ) {

umaData.setMes( 10 );

}

Passagem de Parâmetros com Referências

hoje

0x852ef8b

dia = 0; mes = 10; ano = 0;

umaData

Page 10: Aula 11 - manipulação de ref, polimorfismo e lig. din

10

• Perceba que os valores dos campos do objeto

podem ser alterados dentro do método chamado,

porém, mudanças na própria referência dentro do método não afetam a referência externa. public static void main( String args[] ) {

Data hoje;

hoje = new Data();

funcao(hoje);

System.out.println( hoje.getMes() );

}

void funcao( Data umaData ) {

umaData.setMes( 10 );

umaData = new Data();

umaData.setDia( 22 );

}

Passagem de Parâmetros com Referências

Page 11: Aula 11 - manipulação de ref, polimorfismo e lig. din

11

• Graficamente...

Passagem de Parâmetros com Referências

hoje

0x1402bc84

dia = 22; mes = 0; ano = 0;

0x852ef8b

dia = 0; mes = 10; ano = 0;

umaData

Page 12: Aula 11 - manipulação de ref, polimorfismo e lig. din

12

• Casting de Referências Object

Estundante

EstudanteMonitor

Upcasting

Casting implícito

Ex:

EstudanteMonitor em = new EstudanteMonitor();

Estudante e = em;

Manipulando Referências

Page 13: Aula 11 - manipulação de ref, polimorfismo e lig. din

13

• Exemplos public class Programa {

EstudanteMonitor em = new EstudanteMonitor();

// situação 1

Estudante e = em;

// situação 2

Turma t = new Turma();

t.matricular( em );

}

public class Turma {

...

public void matricular( Estudante e ) {...}

...

}

Origem

Manipulando Referências

Destino

Page 14: Aula 11 - manipulação de ref, polimorfismo e lig. din

14

• O operador binário instanceof tem a seguinte sintaxe:

variavelDeReferencia instanceof TipoDeDestino

• O operador instanceof retorna true se o objeto denotado pela variavelDeReferencia, em tempo de execução é – uma instância da classe TipoDeDestino

– ou uma instância de uma subclasse dela.

• Perceba que esse teste é feito em tempo de execução.

Operador instanceof

Page 15: Aula 11 - manipulação de ref, polimorfismo e lig. din

15

• Em tempo de compilação, porém, é verificado se o tipo da variavelDeReferencia e o TipoDeDestino estão no mesmo ramo da hierarquia de classes.

• Do contrário, acontecerá um erro de compilação.

Operador instanceof

C c = new C();

c instanceof C

c instanceof B

c instanceof A

c instanceof E

c instanceof D

c instanceof Object

A

D

B

C

E

c

true

true

true

false

ERRO COMP.

true

Page 16: Aula 11 - manipulação de ref, polimorfismo e lig. din

16

• Para fazer casting (conversão) da variavelDeReferencia do TipoDeOrigem para o TipoDeDestino, usa-se a seguinte sintaxe:

( TipoDeDestino ) variavelDeReferencia

• O casting acima é possível se o objeto denotado pela variavelDeReferencia, em tempo de execução é: – uma instância da classe TipoDeDestino,

– ou uma instância de uma subclasse dela.

Casting de Referências

Page 17: Aula 11 - manipulação de ref, polimorfismo e lig. din

17

• Quando usar o casting: public class Turma {

...

public Estudante obterEstudante(int mat)

{...}

}

...

EstudanteMonitor em;

em = new EstudanteMonitor(111, “Pedro”, „M‟);

Turma t = new Turma()

t.matricular( em );

EstudanteMonitor em2 = t.obterEstudante( 111 );

Casting de Referências

ERRO DE COMPILAÇÃO, pois o método obterEstudante() retorna um Estudante e

não um EstudanteMonitor.

Page 18: Aula 11 - manipulação de ref, polimorfismo e lig. din

18

• Solução → casting: public class Turma {

...

public Estudante obterEstudante(int mat) {...}

}

...

EstudanteMonitor em;

em = new EstudanteMonitor(111, “Pedro”, „M‟);

Turma t = new Turma()

t.matricular( em );

EstudanteMonitor em2 =

((EstudanteMonitor)t.obterEstudante( 111 ));

Casting de Referências

É necessário dizer ao compilador que o método obterEstudante() vai retornar em tempo de execução,

nesse caso, um objeto da subclasse EstudanteMonitor.

Page 19: Aula 11 - manipulação de ref, polimorfismo e lig. din

19

• Quando usar o casting: ...

EstudanteMonitor em = new EstudanteMonitor();

Turma t = new Turma()

t.matricular( em );

Estudante e = t.obterEstudante( 111 );

e.tirarDuvidas();

...

Casting de Referências

ERRO DE COMPILAÇÃO,

pois a classe Estudante não

possui um método chamado tirarDuvidas().

Page 20: Aula 11 - manipulação de ref, polimorfismo e lig. din

20

• Solução → casting: ...

EstudanteMonitor em = new EstudanteMonitor();

Turma t = new Turma()

t.matricular( em );

Estudante e = t.obterEstudante( 111 );

((EstudanteMonitor) e ).tirarDuvidas();

...

Casting de Referências

É necessário dizer ao compilador que a referência „e‟ denotará, em tempo de

execução, um objeto que possui um método chamado tirarDuvidas().

Page 21: Aula 11 - manipulação de ref, polimorfismo e lig. din

21

Object

Estudante

EstudanteMonitor

Downcasting

É necessário fazer o

casting explícito

Upcasting

Casting implícito

Ex:

EstudanteMonitor em =

new EstudanteMonitor ();

Estudante e = em;

Ex:

Estudante e = new

EstudanteMonitor();

EstudanteMonitor em =

(EstudanteMonitor)e;

Casting de Referências

Page 22: Aula 11 - manipulação de ref, polimorfismo e lig. din

22

• Escrevendo código seguro: combinando Casting e instanceof ...

EstudanteMonitor em = new EstudanteMonitor();

Turma t = new Turma()

t.matricular( em );

Estudante e = t.obterEstudante( 111 );

if ( e instanceof EstudanteMonitor )

{

( (EstudanteMonitor) e ).tirarDuvidas();

}

...

Casting e instanceof

Page 23: Aula 11 - manipulação de ref, polimorfismo e lig. din

23

• Tanto o casting quanto o operador instanceof requerem verificação: – em tempo de compilação, que avalia somente as

referências, e

– em tempo de execução, que avalia o objeto propriamente dito.

• Atenção para a situação abaixo:

// o trecho abaixo passa na compilação,

// mas vai gerar erro de execução

Estudante e = new Estudante();

EstudanteMonitor em = (EstudanteMonitor)e;

Casting e instanceof

O objeto referenciado por „e‟ é, de fato, um Estudante, e não um EstudanteMonitor.

Page 24: Aula 11 - manipulação de ref, polimorfismo e lig. din

24

• Comportamento dos métodos com Casting class Estudante {

public void exibir() { ...

System.out.println("metodo exibir de Estudante");

}

public double lerNota(int prova) {

System.out.println("metodo lerNota de Estudante");

return notas[prova-1];

}...}

class EstudanteMonitor extends Estudante {

public void exibir() {

System.out.println("metodo exibir de

EstudanteMonitor");

}

public void tirarDuvidas() {

System.out.println("metodo tirarDuvidas de

EstudanteMonitor");

}...}

Casting – Usando Métodos

Page 25: Aula 11 - manipulação de ref, polimorfismo e lig. din

25

• Comportamento dos métodos com Casting public class Programa {

public static void main( String args[] ) {

EstudanteMonitor em = new EstudanteMonitor();

em.exibir(); // executa o exibir() redefinido em

// EstudanteMonitor

em.lerNota(1); // executa o lerNota() de Estudante

em.tirarDuvidas(); // executa o tirarDuvidas() de

// EstudanteMonitor

Estudante e = em;

e.exibir(); // executa o exibir() redefinido em

// EstudanteMonitor

// e.tirarDuvidas(); // não existe tirarDuvidas() na

// classe Estudante -> ERRO!!!

((EstudanteMonitor)e).tirarDuvidas(); // Ok

((Estudante)e).exibir(); // executa o exibir()

// do objeto, portanto,

// de EstudanteMonitor

}

}

Casting – Usando Métodos

Page 26: Aula 11 - manipulação de ref, polimorfismo e lig. din

26

• Qual objeto uma referência realmente denotará

em tempo de execução nem sempre se pode

determinar em tempo de compilação.

• Polimorfismo é a capacidade de uma referência

denotar diferentes objetos na hierarquia de

herança em diferentes momentos durante a

execução. Tal referência é uma referência de

supertipo.

• Quando um método é invocado usando uma

referência, a definição do método que será

realmente executada é determinada:

– pela classe denotada pela referência em tempo de

execução, e

– pela assinatura do método.

Polimorfismo

Page 27: Aula 11 - manipulação de ref, polimorfismo e lig. din

27

• Entendendo o Polimorfismo...

(1) EstudanteMonitor em = new EstudanteMonitor();

(2) Estudante e = em;

(3) e.atribuirNota(1, 7.5);

(4) e = new EstudanteEstagiario();

(5) e.atribuirNota(1, 8.5);

Estudante

EstudanteMonitor

e

em

EstudanteEstagiario (1)

(2) (4)

Polimorfismo

Page 28: Aula 11 - manipulação de ref, polimorfismo e lig. din

28

• Usando o Polimorfismo... public class Turma {

...

public Estudante obterEstudante(int mat) {...}

public void matricular (Estudante e) {...}

}

...

EstudanteMonitor em;

em = new EstudanteMonitor(111, “Pedro”, „M‟);

Turma t = new Turma()

t.matricular( em );

EstudanteMonitor em2 =

((EstudanteMonitor)t.obterEstudante( 111 ));

Polimorfismo

Page 29: Aula 11 - manipulação de ref, polimorfismo e lig. din

29

• Numa hierarquia de herança de classes, dois

métodos podem ter o mesmo nome e tipo:

– Definição e redefinição, qual usar?

• O código é escolhido dinamicamente (em tempo

de execução), não estaticamente (em tempo de

compilação).

• Escolha é feita com base na classe do objeto

associado à variável destino do método.

• O mecanismo de ligação dinâmica (dynamic

binding) é responsável por associar uma

solicitação (de um método) a um objeto em tempo

de execução.

Ligação Dinâmica

Page 30: Aula 11 - manipulação de ref, polimorfismo e lig. din

30

• Observando o emprego do Polimorfismo e da Ligação Dinâmica

public class Programa {

public static void main( String args[] ) {

Estudante e = new Estudante(“Pedro”);

e.exibir(); // executa o exibir() de Estudante

e = new EstudanteMonitor(“Maria”);

e.exibir(); // executa o exibir() redefinido em

// EstudanteMonitor

e = new EstudanteEstagiario(“Fernanda”);

e.exibir(); // executa o exibir() redefinido em

// EstudanteEstagiario

}

}

Ligação Dinâmica

Page 31: Aula 11 - manipulação de ref, polimorfismo e lig. din

31

Questionário

1. O que é upcasting e downcasting?

2. Em que situação ou situações é necessário fazer casting explicíto?

3. Em que situação ou situações não é necessário fazer casting explicíto?

4. Quando o operador instanceof retorna verdadeiro?

5. Que validação é feita em tempo de compilação quando se usa o operador instanceof?

6. Que validação é feita em tempo de execução quando se usa o operador instanceof?

7. Qual a relação do casting com o operador instanceof?

8. Por que conversões usando casting são ditas inseguras?

9. O que é polimorfismo?

10. Na herança de classes, quando há redefinição de métodos, o que se pode dizer sobre a execução do método?

11. Explique o mecanismo de ligação dinâmica.

Page 32: Aula 11 - manipulação de ref, polimorfismo e lig. din

32

Prática de Laboratório

1. Implementar o programa do slide 27 para testar o emprego do casting.

2. Implementar o programa do slide 33 para testar o emprego do polimorfismo e da ligação dinâmica.

3. Criar uma classe chamada „Apresentador‟ que possui um único método chamado apresentar(Estudante e), que recebe como argumento um Estudante e exibe seus dados, ou seja, chama o método exibir do objeto passado.

4. Codifique um programa para criar um apresentador e três estudantes (comum, monitor e estagiário) e passá-los ao apresentador para exibir seus dados. Observe o emprego do polimorfismo e da ligação dinâmica.