• Nenhum resultado encontrado

Polimorfismo. BCC Programação Orientada a Objectos(POO) Departamento de Computação - UFOP Baseado nos slides do Prof. Marco Antônio Carvalho

N/A
N/A
Protected

Academic year: 2021

Share "Polimorfismo. BCC Programação Orientada a Objectos(POO) Departamento de Computação - UFOP Baseado nos slides do Prof. Marco Antônio Carvalho"

Copied!
105
0
0

Texto

(1)

Polimorfismo

BCC 221 - Programa¸

ao Orientada a Objectos(POO)

Guillermo C´

amara-Ch´

avez

Departamento de Computa¸c˜ao - UFOP Baseado nos slides do Prof. Marco Antˆonio Carvalho

(2)

I

O Polimorfismo ´

e um recurso que nos permite programar

“em geral” ao inv´

es de programar espec´ıficamente ;

I

Vamos supor um programa que simula o movimento de v´

arios

(3)

Introdu¸c˜

ao

I

Trˆ

es classes representam os animais pesquisados:

I Peixe;

I Sapo;

I P´assaro

I

Todos herdam da classe Animal

(4)

I

Cada classe derivada implementa o m´

etodo mover();

I

O programa mant´

em um vetor de ponteiros para objetos

das classes derivadas da classe Animal

I

Para simular o movimento do animal, envia-se a mesma

(5)

Introdu¸c˜

ao (cont.)

I

Cada objeto responder´

a de uma maneira diferente;

I

A mensagem ´

e enviada genericamente

I

Cada objeto sabe como modificar sua posi¸

ao de acordo com

(6)
(7)

Introdu¸c˜

ao (cont.)

I

Atrav´

es do polimorfismo pode-se projetar e implementar

sistemas que sejam facilmente extens´ıveis

I

Novas classes podem ser adicionadas com pouca ou

mesmo nenhuma modifica¸

ao `

as partes gerais do programa

(8)

I

Por exemplo, se criarmos uma classe Tartaruga somente

precisamos implementar:

I a classe e,

I a parte da simula¸c˜ao que instˆancia o objeto

I

As partes que processam a classe Animal genericamente n˜

ao

(9)

Outro Exemplo

I

Vamos imaginar que temos um programa que controla um

jogo que cont´

em as seguintes classes/objetos/elementos

I Marciano;

I Plutoniano;

I RaioLaser;

I NaveEspacial.

(10)

I

Para gerenciar os elementos presentes na tela, mantemos um

vetor com ponteiros para objetos da classe ObjetoEspacial

I

Cada objeto possui um m´

etodo desenhar(), que o imprime na

(11)

Polimorfismo (cont.)

I

Para atualizar a tela do jogo, ´

e necess´

ario redesenhar todos

os seus elementos.

I

Enviar a mesma mensagem para cada objeto do vetor

(12)

I

etodo desenhar():

I Cada objeto redefine este m´etodo para suas especificidades;

I A classe ObjetoEspacial determina que as classes derivadas o implementem.

I

Podem ser criadas novas classes para outros elementos do

jogo

(13)
(14)

I

Vamos supor um programa que simula diversos animais

emitindo sons.

I

Cada personagem emite seu pr´

oprio som

I Cada personagem ´e um objeto que invoca seu pr´oprio m´etodo emitirSom();

I A classe derivada sabe como deve ser implementado.

I

Em uma hierarquia de heran¸

ca, podemos criar uma classe

Mamifero, a partir dela derivam Boi, cachorro, gato, bode,

etc.

(15)

Implementa¸c˜

oes

c l a s s M a m i f e r o { p u b l i c: v o i d e m i t i r S o m ( ) {c o u t << " \ nsom de mamifero " ; } ; } ; c l a s s C a c h o r r o : p u b l i c M a m i f e r o { p u b l i c: v o i d e m i t i r S o m ( ) {c o u t << " \n woof woof " ; } ; } ; c l a s s Vaca : p u b l i c M a m i f e r o { p u b l i c: v o i d e m i t i r S o m ( ) {c o u t << " \n moo moo " ; } ; } ; c l a s s Bode : p u b l i c M a m i f e r o { p u b l i c: v o i d e m i t i r S o m ( ) {c o u t << " \n baa baa " ; } ; } ;

(16)

i n t main ( ) { C a c h o r r o c a c h o r r o ; Vaca v a c a ; Bode bode ; Gato g a t o ; c a c h o r r o . e m i t i r S o m ( ) ; v a c a . e m i t i r S o m ( ) ; bode . e m i t i r S o m ( ) ; g a t o . e m i t i r S o m ( ) ; r e t u r n 0 ; }

(17)

Sem Polimorfismo (cont.)

woof woof moo moo baa baa meow meow

(18)

c l a s s M a m i f e r o { p u b l i c: v i r t u a l v o i d e m i t i r S o m ( ) {c o u t << " \ nsom de mamifero " ; } ; } ; c l a s s C a c h o r r o : p u b l i c M a m i f e r o { p u b l i c: v o i d e m i t i r S o m ( ) {c o u t << " \n woof woof " ; } ; } ; c l a s s Vaca : p u b l i c M a m i f e r o { p u b l i c: v o i d e m i t i r S o m ( ) {c o u t << " \n moo moo " ; } ; } ; c l a s s Bode : p u b l i c M a m i f e r o { p u b l i c: v o i d e m i t i r S o m ( ) {c o u t << " \n baa baa " ; } ; } ; c l a s s Gato : p u b l i c M a m i f e r o { p u b l i c: v o i d e m i t i r S o m ( ) {c o u t << " \n meow meow " ; } ;

(19)

Polimorfismo (cont.)

i n t main ( ) { M a m i f e r o ∗ p [ 5 ] = { new C a c h o r r o ( ) , new Vaca ( ) , new Bode ( ) , new Gato ( ) } ; } f o r (i n t i = 0 ; i < 5 ; i ++) { p [ i ]−> e m i t i r S o m ( ) ; } r e t u r n 0 ; }

(20)

woof woof moo moo baa baa meow meow

(21)

Polimorfismo (cont.)

I

Como vimos na aula anterior, ´

e poss´ıvel realizar a convers˜

ao

de tipo entre classe base e derivada

I

Um objeto da classe base pode receber um objeto da classe

derivada

(22)

I

Tamb´

em ´

e poss´ıvel fazer o mesmo com ponteiros

I

Um ponteiro para a classe base pode apontar para um objeto

da classe derivada

(23)

Polimorfismo (cont.)

I

Note que a classe Derivada

redefine o m´

etodo print();

I

O m´

etodo original imprime

os atributos a, b e c;

I

O m´

etodo redefinido

acrescenta a impress˜

ao dos

atributos d , e e f .

Base –a: int –b: int –c: int +Base() +getABC() +setABC() +print() Derivada –d: int –e: int –f: int +Derivada() +getDEF()

(24)

c l a s s Base { i n t a , b , c ; p u b l i c: Base (i n t a =0 ,i n t b =0 ,i n t c = 0 ) : a ( a ) , b ( b ) , c ( c ) { } v o i d p r i n t ( ) { c o u t << " \n Base : " << a << " ,"<< b << " ," <<c ; } } ; c l a s s D e r i v a d a : p u b l i c Base { i n t d , e , f ; p u b l i c: D e r i v a d a (i n t d =0 ,i n t e =0 ,i n t f = 0 ) : d ( d ) , e ( e ) , f ( f ) { } v o i d p r i n t ( ) { c o u t << " \n Derivada " << d << " ,"<< e << " ," <<f ; }

(25)

Polimorfismo (cont.)

#i n c l u d e <i o s t r e a m > #i n c l u d e " base . h " u s i n g n a m e s p a c e s t d ; i n t main ( ) { Base o b j B ( 1 , 2 , 3 ) , ∗ p o b j B=n u l l p t r; D e r i v a d a objD ( 4 , 5 , 6 ) , ∗ p o b j D=n u l l p t r; p o b j B = &o b j B ; p o b j B −>p r i n t ( ) ; p o b j D = &objD ; P−objD−>p r i n t ( ) ; p o b j B = &objD ; p o b j B −>p r i n t ( ) ;

(26)

#i n c l u d e <i o s t r e a m > #i n c l u d e " base . h " u s i n g n a m e s p a c e s t d ; i n t main ( ) { Base o b j B ( 1 , 2 , 3 ) , ∗ p o b j B=n u l l p t r; D e r i v a d a objD ( 4 , 5 , 6 ) , ∗ p o b j D=n u l l p t r; p o b j B = &o b j B ; // aponta para objeto da classe Base

p o b j B −>p r i n t ( ) ; // invoca m´etodo da classe Base

p o b j D = &objD ; // aponta para objeto da classe Derivada

P−objD−>p r i n t ( ) ; // invoca m´etodo da classe Derivada

p o b j B = &objD ; // aponta para objeto da classe Derivada

p o b j B −>p r i n t ( ) ; // invoca m´etodo da classe Base

r e t u r n 0 ; }

(27)

Polimorfismo (cont.)

Base D e r i v a d a Base

(28)

I

Este tipo de constru¸

ao ´

e permitido pelo compilador por

conta do relacionamento de heran¸

ca

(29)

Polimorfismo (cont.)

I

A funcionalidade invocada depende do handle (tipo do

ponteiro ou referˆ

encia) utilizado para invoc´

a-la

I

ao depende do tipo do objeto apontado pelo handle.

I

Utilizando um tipo especial de m´

etodo podemos fazer com

que este comportamento seja invertido

(30)

#i n c l u d e <i o s t r e a m > #i n c l u d e " base . h " u s i n g n a m e s p a c e s t d ; i n t main ( ) { Base o b j B ( 1 , 2 , 3 ) , ∗ p o b j B=n u l l p t r; D e r i v a d a objD ( 4 , 5 , 6 ) , ∗ p o b j D=n u l l p t r; p o b j B = &o b j B ; // aponta para objeto da classe Base

p o b j B −>p r i n t ( ) ; // invoca m´etodo da classe Base // ERRO! n˜ao ´e poss´ıvel apontar para objeto da classe Base

p o b j D = &o b j B ;

// Erro! Um objeto da classe base n˜ao // ´e um objeto da classe derivada

p o b j D −>p r i n t ( ) ;

r e t u r n 0 ; }

(31)

Fun¸c˜

oes Virtuais

I

O tipo do handle determina a vers˜

ao de um m´

etodo que ser´

a

invocada

I N˜ao o tipo do objeto apontado

Base ∗ p o b j B=n u l l p t r; D e r i v a d a objD ( 4 , 5 , 6 ) ;

p o b j B = &objD ; // aponta para objeto da classe Derivada

(32)

I

Com fun¸

oes virtuais, ocorre o contr´

ario

I

O tipo do objeto apontado determina qual ser´

a a vers˜

ao do

(33)

Fun¸c˜

oes Virtuais (cont.)

I

Voltando ao exemplo do jogo espacial, cada classe derivada da

classe ObjetoEspacial define um objeto de formato

geom´

etrico diferente

I

Cada classe define seu pr´

oprio m´

etodo desenhar()

I

Podemos atrav´

es de um ponteiro para classe base invocar o

etodo desenhar();

I

Por´

em, seria ´

util se o programa determinasse

dinamicamente (tempo de execu¸

ao) qual m´

etodo deve

(34)

I

Para permitir este tipo de comportamento dinˆ

amico,

declaramos na classe base o m´

etodo desenhar() como uma

fun¸

ao virtual

I O redefinimos nas classes derivadas;

I O m´etodo sobrescrito possui o mesmo prot´otipo do original (assinatura e tipo de retorno).

(35)

Fun¸c˜

oes Virtuais (cont.)

I

Para declararmos um m´

etodo como virtual, adicionamos a

palavra chave virtual antes de seu prot´

otipo

v i r t u a l v o i d d e s e n h a r ( )

I

Se uma classe n˜

ao sobrescrever um m´

etodo virtual, ela herda

(36)

I

Definindo o m´

etodo como virtual na classe base, ele

permanecer´

a assim por toda a hierarquia de heran¸

ca

I Mesmo que as classes derivadas a sobrescrevam e n˜ao a declarem como virtual novamente;

I E uma boa pr´´ atica declarar o m´etodo como virtual por toda a hierarquia de classes.

(37)

Resolu¸c˜

ao Est´

atica e Dinˆ

amica

I

As instru¸c˜

oes de chamada a m´

etodos n˜

ao virtuais s˜

ao

resolvidas em tempo de compila¸

ao

I E traduzidas em chamadas a fun¸c˜oes de endere¸co fixo;

I Isso faz com que a instru¸c˜ao seja vinculada `a fun¸c˜ao antes de sua execu¸c˜ao;

(38)

I

Resolu¸

ao Est´

atica

I Acontece quando invocamos um m´etodo atrav´es de um objeto, usando o operador .

(39)

Resolu¸c˜

ao Dinˆ

amica

I

Quando uma instru¸c˜

ao de chamada a um m´

etodo virtual ´

e

encontrada pelo compilador, ele n˜

ao tem como identificar

qual ´

e o m´

etodo associado em tempo de compila¸

ao.

I

Quando utilizamos ponteiros (ou referˆ

encias) para objetos,

o compilador n˜

ao conhece qual ´

e a classe do endere¸

co

contido no ponteiro antes de o programa ser executado;

I

A instru¸

ao ´

e avaliada em tempo de execu¸

ao;

(40)

Poligono –base –altura +setValores() +calculaArea() Retangulo +calculaArea() Triangulo +calculaArea()

(41)

Exemplo (cont.)

c l a s s P o l i g o n o { p r o t e c t e d: d o u b l e b a s e , a l t u r a ; p u b l i c: v o i d s e t V a l o r e s (d o u b l e a , d o u b l e b ) { b a s e=a ; a l t u r a=b ; } v i r t u a l d o u b l e a r e a (v o i d) { r e t u r n 0 ; }

(42)

c l a s s R e t a n g u l o : p u b l i c P o l i g o n o { p u b l i c: d o u b l e a r e a (v o i d) { r e t u r n ( b a s e ∗ a l t u r a ) ; } } ; c l a s s T r i a n g u l o : p u b l i c P o l i g o n o { p u b l i c: d o u b l e a r e a (v o i d) { r e t u r n ( b a s e ∗ a l t u r a / 2 ) ; } } ;

(43)

Exemplo (cont.)

i n t main ( ) { R e t a n g u l o r e c t ; T r i a n g u l o t r g l ; P o l i g o n o p o l y ; P o l i g o n o ∗ p p o l y 1 = &r e c t ; P o l i g o n o ∗ p p o l y 2 = & t r g l ; P o l i g o n o ∗ p p o l y 3 = &p o l y ; p p o l y 1 −>s e t V a l o r e s ( 4 , 5 ) ; p p o l y 2 −>s e t V a l o r e s ( 4 , 5 ) ; p p o l y 3 −>s e t V a l o r e s ( 4 , 5 ) ; c o u t << p p o l y 1 −>a r e a ( ) << e n d l ; c o u t << p p o l y 2 −>a r e a ( ) << e n d l ; c o u t << p p o l y 3 −>a r e a ( ) << e n d l ;

(44)

I

As trˆ

es classes (Poligono, Retangulo e Triangulo)

possuem os mesmos membros: base, altura, setValores()

e area().

I

area() foi definida como virtual porque ´

e redefinida depois

(45)

Outro Exemplo

I

Considere uma classe Ve´

ıculo com duas classes derivadas

Autom´

ovel e Bicicleta

I

Essas classes tˆ

em trˆ

es m´

etodos, definidos para ve´ıculos de

forma geral e redefinidas mais especificamente para

autom´

oveis e bicicletas;

(46)

I

As fun¸c˜

oes s˜

ao:

I VerificaLista(): para verificar o que precisa ser analisado no ve´ıculo;

I Reparar(): para realizar os reparos e a manuten¸c˜ao necess´aria

I Limpa(): para realizar procedimentos de limpeza do ve´ıculo

I

A aplica¸c˜

ao Oficina define um objeto que recebe objetos da

classe Ve´

ıculos.

I Para cada ve´ıculo recebido, a oficina executa na sequencia os trˆes m´etodos da classe Ve´ıculo.

(47)

Outro Exemplo (cont.)

c l a s s V e i c u l o { p u b l i c: v i r t u a l v o i d v e r i f i c a L i s t a ( ) { c o u t<<" \n Verifica Veiculo " ; } ; v i r t u a l v o i d r e p a r a r ( ) { c o u t<<" \n Repara Veiculo " ; } ; v i r t u a l v o i d l i m p a ( ) { c o u t<<" \n Limpa Veiculo " ; } ; } ;

(48)

c l a s s A u t o m o v e l : p u b l i c V e i c u l o { p u b l i c: v o i d v e r i f i c a L i s t a ( ) {c o u t<<" \n Verifica Automovel " ; } ; v o i d r e p a r a r ( ) {c o u t<<" \n Repara Automovel " ; } ; v o i d l i m p a ( ) {c o u t<<" \n Limpa Automovel " ; } ; } ; c l a s s B i c i c l e t a : p u b l i c V e i c u l o { p u b l i c: v o i d v e r i f i c a L i s t a ( ) {c o u t<<" \n Verifica Bicicleta " ; } ; v o i d r e p a r a r ( ) {c o u t<<" \n Repara Bicicleta " ; } ; v o i d l i m p a ( ) {c o u t<<" \n Limpa Bicicleta " ; } ; } ;

(49)

Outro Exemplo (cont.)

I

ao h´

a como saber no momento de programa¸

ao se a

Oficina estar´

a recebendo um autom´

ovel ou uma bicicleta

I

O momento de decis˜

ao sobre qual m´

etodo ser´

a aplicado s´

o

(50)

c l a s s O f i c i n a { i n t R ; p u b l i c: V e i c u l o ∗ p r o x i m o ( ) ; v o i d m a n t e r ( V e i c u l o ∗ v ) ; i n t g e t R ( ) ; } ;

(51)

Outro Exemplo (cont.)

V e i c u l o ∗ O f i c i n a : : p r o x i m o ( ) { V e i c u l o ∗ v ; R = r a n d ( ) ; i f (R % 2 == 0 ) v = new A u t o m o v e l ( ) ; e l s e v = new B i c i c l e t a ( ) ; r e t u r n v ; } v o i d O f i c i n a : : m a n t e r ( V e i c u l o ∗ v ) { v−> V e r i f i c a L i s t a ( ) ; v−>R e p a r a r ( ) ; v−>Limpa ( ) ; } i n t O f i c i n a : : g e t R ( ) {

(52)

i n t main ( ) { O f i c i n a Of ; V e i c u l o ∗ pv ; i n t n = 0 ; w h i l e ( n < 6 ) { pv = Of . p r o x i m o ( ) ; c o u t<<e n d l <<Of . g e t R ()<< e n d l ; Of . m a n t e r ( pv ) ; n++; d e l e t e pv ; } r e t u r n 0 ; }

(53)

Outro Exemplo (cont.)

Na tela ´

e mostrado

41 V e r i f i c a B i c i c l e t a R e p a r a B i c i c l e t a Limpa B i c i c l e t a 18467 V e r i f i c a B i c i c l e t a R e p a r a B i c i c l e t a Limpa B i c i c l e t a 6334 V e r i f i c a A u t o m o v e l 26500 V e r i f i c a A u t o m o v e l R e p a r a A u t o m o v e l Limpa A u t o m o v e l 19169 V e r i f i c a B i c i c l e t a R e p a r a B i c i c l e t a Limpa B i c i c l e t a 15724 V e r i f i c a A u t o m o v e l

(54)

I

O m´

etodo Of.proximo() realiza uma atribui¸c˜

ao de

I um objeto Autom´ovel `a vari´avel R quando o valor do n´umero aleat´orio gerado ´e par.

I um objeto Bicicleta `a vari´avel R quando o valor do n´umero aleat´orio gerado ´e ´ımpar.

(55)

Sum´

ario das Atribu¸c˜

oes permitidas entre Ponteiros de

Classe Base e Derivada

I

Apesar de um objeto de uma classe derivada ser um objeto

da classe base, temos dois tipos de objetos completamente

diferentes.

I

um objeto de uma classe derivada pode ser tratado como

um objeto da classe base

(56)

Classe Base e Derivada (cont.)

I

O contr´

ario n˜

ao ´

e v´

alido (objeto da classe Base ser tratado

como da classe Derivada)

I Os membros da classe derivada s˜ao indefinidos para objetos da classe base;

I E poss´ıvel realizar um downcasting;´

(57)

Sum´

ario das Atribu¸c˜

oes Permitidas

Considere o seguinte caso:

c l a s s Base { p u b l i c: Base ( ) {} v o i d p r i n t ( ) { c o u t << " \n Base " ; } } ; c l a s s D e r i v a d a : p u b l i c Base { p u b l i c: D e r i v a d a ( ) { } v o i d p r i n t ( ) { c o u t << " \n Derivada " ; } i n t main ( ) { Base objB , ∗ p o b j B=n u l l p t r; D e r i v a d a objD , ∗ p o b j D=n u l l p t r; . . . r e t u r n 0 ; }

(58)

I

Apontar um ponteiro base para um objeto base ´

e simples

p o b j B = &o b j B ;

I

Apontar um ponteiro derivado para um objeto derivado ´

e

simples

(59)

Sum´

ario das Atribu¸c˜

oes Permitidas (cont.)

I

Apontar um ponteiro base para um objeto derivado ´

e

seguro

p o b j B = &objD ;

I O ponteiro deve ser utilizado apenas para realizar chamadas da classe base;

p o b j B −>p r i n t 2 ( ) ; // ERRO n˜ao ´e membro da classe Base

I Chamadas da classe derivada gerar˜ao erros, a n˜ao ser que seja utilizado downcasting, o que n˜ao ´e seguro

(60)

I

Apontar um ponteiro derivado para um objeto base gera

um erro de compila¸

ao

p o b j D = &o b j B ; // ERRO de compila¸c˜ao

(61)

Classes Abstratas e M´

etodos Virtuais Puros

I

Quando pensamos em classes, podemos pensar que os

programas as instanciar˜

ao, criando objetos daquele tipo

I Por´em, existem casos em que ´e ´util definir classes que n˜ao ser˜ao instanciadas nunca.

(62)

I

Tais classes s˜

ao denominadas classes abstratas

I Como s˜ao normalmente utilizadas como base em hierarquias de heran¸ca, tamb´em s˜ao conhecidas como classes base

abstratas.

I S˜ao classes “incompletas”, que devem ser completadas por classes derivadas;

(63)

Classes Abstratas

I

Classes que podem ser instanciadas s˜

ao chamadas de

classes concretas

I Providenciam implementa¸c˜ao para todos os m´etodos que definem.

I

O prop´

osito de uma classe base abstrata ´

e exatamente

(64)

I

Classes base abstratas s˜

ao gen´

ericas demais para

definirem com precis˜

ao objetos reais e serem instanciadas

I

As classes concretas cuidam das especificidades

necess´

arias para que objetos sejam bem modelados e

(65)

Classes Abstratas (cont.)

I

Em uma hierarquia de heran¸ca, n˜

ao ´

e obrigat´

oria a existˆ

encia

de uma base abstrata

I

Por´

em, bons projetos de engenharia de software possuem

hierarquias de heran¸

ca cujo topo ´

e formado por classes

abstratas;

(66)

I

Em alguns casos, classes abstratas constituem

completamente os primeiros n´ıveis de uma hierarquia de

heran¸

ca.

I

Uma classe ´

e determinada abstrata automaticamente

quando um ou mais de seus m´

etodos virtuais s˜

ao

(67)

etodos Virtuais Puros

I

Para declararmos um m´

etodo como virtual puro, utilizamos a

seguinte sintaxe:

v i r t u a l v o i d p r i n t ( ) = 0 ;

I

O “=0” ´

e conhecido como especificador puro

I N˜ao se trata de atribui¸c˜ao;

I M´etodos virtuais n˜ao possuem implementa¸c˜ao;

(68)

I

A diferen¸

ca entre um m´

etodo virtual e um m´

etodo virtual

puro ´

e que o primeiro opcionalmente possui implementa¸

ao na

classe base

I

O segundo requer obrigatoriamente uma implementa¸

ao nas

(69)

etodos Virtuais Puros (cont.)

I

Um m´

etodo virtual puro nunca ser´

a executada na classe base

I

Deve ser sobrescrita nas classes derivadas;

I

Serve para fornecer uma interface polim´

orfica para classes

(70)

I

Novamente, uma classe que possui um m´

etodo virtual

puro n˜

ao pode ser instanciada

I

Invocar um m´

etodo virtual puro geraria erro.

I

Pode-se declarar ponteiros para uma classe base abstrata e

(71)

Exemplo de Polimorfismo

A utiliza¸c˜

ao de polimorfismo ´

e particularmente eficiente na

implementa¸c˜

ao de sistemas de software em camadas

I

Como um sistema operacional;

I

Cada tipo de dispositivo f´ısico opera de uma forma diferente

(72)

I

Uma classe base abstrata pode ser utilizada para gerar

uma interface para todos os dispositivos

I Todo o comportamento necess´ario pode ser implementado como m´etodos virtuais puros;

I Cada dispositivo sobrescreve os m´etodos em suas pr´oprias classes, derividas da classe base abstrata.

I

Para cada novo dispositivo, instala-se o driver, que cont´

em

(73)

Outro Exemplo de Polimorfismo

Outro aplica¸c˜

ao ´

util do polimorfismo ´

e na cria¸

ao de classes de

iteradores

I

Iteradores s˜

ao utilizados para percorrer estruturas de dados ou

(cole¸c˜

oes)

I Vetores, listas, ´arvores, etc;

I Percorrem os objetos de uma agrega¸c˜ao sem expˆor sua implementa¸c˜ao interna

(74)

I

Pagamento de funcion´

arios: 4 tipos de funcion´

arios

1. Sal´ario fixo semanal;

2. Horistas (hora extra depois de 40 horas);

3. Comissionados;

4. Assalariados Comissionados

I

A id´

eia ´

e realizar o c´

alculo dos pagamentos utilizando

comportamento polim´

orfico.

I

Na aula sobre heran¸

ca, t´ınhamos apenas os dois ´

ultimos tipos

de funcion´

arios, em uma hierarquia de heran¸

ca.

(75)
(76)

I

Neste exemplo, n˜

ao h´

a uma classe que absorva o

comportamento das outras

I

Ser´

a necess´

ario criar uma outra classe que sirva de base para

os outras

I Representar´a um funcion´ario gen´erico

I Nome, sobrenome e documento s˜ao os atributos;

I Getters e setters para cada um dos atributos.

I Um print para todos os atributos.

(77)

Exemplo: Funcionarios (cont.)

I

Teremos quatro classes derivadas, cada uma representando

um tipo de funcion´

ario

I A diferen¸ca se d´a basicamente pela forma em que o pagamento ´e calculado (m´etodo earnings()).

(78)
(79)

Exemplo: Funcionarios (cont.)

Dada a hierarquia estabelecida e a necessidade de polimorfismo:

I

Os getters e setters da classe base ser˜

ao m´

etodos concretos;

I

O m´

etodo print ser´

a um m´

etodo virtual

I Ter´a implementa¸c˜ao, mas opcionalmente poder´a ser sobrescrito pelas classes derivadas.

I

O m´

etodo earnings ser´

a um m´

etodo virtual puro

I N˜ao ter´a implementa¸c˜ao e obrigatoriamente ser´a sobrescrito pelas classes derivadas.

(80)
(81)
(82)

#i f n d e f EMPLOYEE H

#d e f i n e EMPLOYEE H

#i n c l u d e <s t r i n g> // classe string padr˜ao C++

u s i n g s t d : :s t r i n g; c l a s s E m p l o y e e { s t r i n g f i r s t N a m e ; s t r i n g l a s t N a m e ; s t r i n g s o c i a l S e c u r i t y N u m b e r ; p u b l i c: E m p l o y e e (c o n s t s t r i n g=" " , c o n s t s t r i n g&=" " , c o n s t s t r i n g&=" " ) ; v o i d s e t F i r s t N a m e ( c o n s t s t r i n g& ) ; s t r i n g g e t F i r s t N a m e ( ) c o n s t; v o i d s e t L a s t N a m e ( c o n s t s t r i n g& ) ; s t r i n g g e t L a s t N a m e ( ) c o n s t;

(83)

Employee.h (cont.)

. . .

v o i d s e t S o c i a l S e c u r i t y N u m b e r ( c o n s t s t r i n g& ) ;

s t r i n g g e t S o c i a l S e c u r i t y N u m b e r ( ) c o n s t;

// a fun¸c˜ao virtual pura cria a classe b´asica abstrata Employee

v i r t u a l d o u b l e e a r n i n g s ( ) c o n s t = 0 ; // virtual pura

v i r t u a l v o i d p r i n t ( ) c o n s t; // virtual

} ; // fim da classe Employee

(84)

#i n c l u d e <i o s t r e a m >

u s i n g s t d : :c o u t;

#i n c l u d e " Employee . h " // Defini¸c˜ao da classe Employee // construtor E m p l o y e e : : E m p l o y e e ( c o n s t s t r i n g & f i r s t , c o n s t s t r i n g &l a s t , c o n s t s t r i n g &s s n ) : f i r s t N a m e ( f i r s t ) , l a s t N a m e ( l a s t ) , s o c i a l S e c u r i t y N u m b e r ( s s n ) {} } // fim do construtor Employee

(85)

Employee.cpp

// imprime informa¸c˜oes de Employee (virtual, mas n˜ao virtual pura)

v o i d E m p l o y e e : : p r i n t ( ) c o n s t

{

c o u t << g e t F i r s t N a m e ( ) << ’ ’ << g e t L a s t N a m e ( ) << " \ nsocial security number : "

<< g e t S o c i a l S e c u r i t y N u m b e r ( ) ; } // fim da fun¸c˜ao print

(86)

#i f n d e f HOURLY H

#d e f i n e HOURLY H

#i n c l u d e " Employee . h " // Defini¸c˜ao da classe Employee

c l a s s H o u r l y E m p l o y e e : p u b l i c E m p l o y e e {

d o u b l e wage ; // sal´ario por hora

d o u b l e h o u r s ; // horas trabalhadas durante a semana

p u b l i c: H o u r l y E m p l o y e e ( c o n s t s t r i n g &=" " , c o n s t s t r i n g &=" " , c o n s t s t r i n g &=" " , d o u b l e = 0 . 0 , d o u b l e = 0 . 0 ) ; v o i d setWage ( d o u b l e ) ; d o u b l e getWage ( ) c o n s t; v o i d s e t H o u r s ( d o u b l e ) ; d o u b l e g e t H o u r s ( ) c o n s t;

// palavra-chave virtual assinala inten¸c˜ao de sobrescrever

v i r t u a l d o u b l e e a r n i n g s ( ) c o n s t; // calcula os rendimentos

v i r t u a l v o i d p r i n t ( ) c o n s t; // imprime HourlyEmployee

(87)

HourlyEmployee.cpp

u s i n g s t d : :c o u t;

#i n c l u d e " H o u r l y E m p l o y e e . h " // Defini¸c˜ao da classe HourlyEmployee // construtor H o u r l y E m p l o y e e : : H o u r l y E m p l o y e e ( c o n s t s t r i n g & f i r s t , c o n s t s t r i n g &l a s t , c o n s t s t r i n g &s s n , d o u b l e h o u r l y W a g e , d o u b l e h o u r s W o r k e d ) : E m p l o y e e ( f i r s t , l a s t , s s n ) {

setWage ( h o u r l y W a g e ) ; // valida a remunera¸c˜ao por hora

s e t H o u r s ( h o u r s W o r k e d ) ; // valida as horas trabalhadas

(88)

// calcula os rendimentos;

// sobrescreve a fun¸c˜ao virtual pura earnings em Employee

d o u b l e H o u r l y E m p l o y e e : : e a r n i n g s ( ) c o n s t

{

i f ( g e t H o u r s ( ) <= 40 ) // nenhuma hora extra

r e t u r n getWage ( ) ∗ g e t H o u r s ( ) ;

e l s e

r e t u r n 40 ∗ getWage ( ) + ( ( g e t H o u r s ( ) − 40 ) ∗ getWage ( ) ∗ 1 . 5 ) ;

(89)

HourlyEmployee.cpp (cont.)

// imprime informa¸c˜oes do HourlyEmployee

v o i d H o u r l y E m p l o y e e : : p r i n t ( ) c o n s t

{

c o u t << " hourly employee : " ;

E m p l o y e e : : p r i n t ( ) ; // reutiliza¸c˜ao de c´odigo

c o u t << " \ nhourly wage : " << getWage ( ) << " ; hours worked : " << g e t H o u r s ( ) ; } // fim da fun¸c˜ao print

(90)

#i f n d e f SALARIED H

#d e f i n e SALARIED H

#i n c l u d e " Employee . h " // Defini¸c˜ao da classe Employee

c l a s s S a l a r i e d E m p l o y e e : p u b l i c E m p l o y e e {

d o u b l e w e e k l y S a l a r y ; // sal´ario por semana

p u b l i c:

S a l a r i e d E m p l o y e e ( c o n s t s t r i n g &=" " , c o n s t s t r i n g &=" " ,

c o n s t s t r i n g &=" " , d o u b l e = 0 . 0 ) ;

v o i d s e t W e e k l y S a l a r y ( d o u b l e ) ;

d o u b l e g e t W e e k l y S a l a r y ( ) c o n s t;

// palavra-chave virtual assinala inten¸c˜ao de sobrescrever

v i r t u a l d o u b l e e a r n i n g s ( ) c o n s t; // calcula os rendimentos

v i r t u a l v o i d p r i n t ( ) c o n s t; // imprime SalariedEmployee

} ; // fim da classe SalariedEmployee

(91)

SalariedEmployee.h

#i n c l u d e <i o s t r e a m > u s i n g s t d : :c o u t; #i n c l u d e " S a l a r i e d E m p l o y e e . h " // construtor S a l a r i e d E m p l o y e e : : S a l a r i e d E m p l o y e e ( c o n s t s t r i n g & f i r s t , c o n s t s t r i n g &l a s t , c o n s t s t r i n g &s s n , d o u b l e s a l a r y ) : E m p l o y e e ( f i r s t , l a s t , s s n ) { s e t W e e k l y S a l a r y ( s a l a r y ) ; } // fim do construtor SalariedEmployee

(92)

// calcula os rendimentos;

// sobrescreve a fun¸c˜ao virtual pura earnings em Employee

d o u b l e S a l a r i e d E m p l o y e e : : e a r n i n g s ( ) c o n s t

{

r e t u r n g e t W e e k l y S a l a r y ( ) ; } // fim da fun¸c˜ao earnings

// imprime informa¸c˜oes de SalariedEmployee

v o i d S a l a r i e d E m p l o y e e : : p r i n t ( ) c o n s t

{

c o u t << " salaried employee : " ; E m p l o y e e : : p r i n t ( ) ;

c o u t << " \ nweekly salary : " << g e t W e e k l y S a l a r y ( ) ; } // fim da fun¸c˜ao print

(93)

ComissionEmployee.h

#i f n d e f COMMISSION H

#d e f i n e COMMISSION H

#i n c l u d e " Employee . h " // Defini¸c˜ao da classe Employee

c l a s s C o m m i s s i o n E m p l o y e e : p u b l i c E m p l o y e e {

d o u b l e g r o s s S a l e s ; // vendas brutas semanais

d o u b l e c o m m i s s i o n R a t e ; // porcentagem da comiss˜ao p u b l i c: C o m m i s s i o n E m p l o y e e ( c o n s t s t r i n g &=" " , c o n s t s t r i n g &=" " , c o n s t s t r i n g &=" " , d o u b l e = 0 . 0 , d o u b l e = 0 . 0 ) ; v o i d s e t C o m m i s s i o n R a t e ( d o u b l e ) ; d o u b l e g e t C o m m i s s i o n R a t e ( ) c o n s t; v o i d s e t G r o s s S a l e s ( d o u b l e ) ; d o u b l e g e t G r o s s S a l e s ( ) c o n s t;

// palavra-chave virtual assinala inten¸c˜ao de sobrescrever

(94)

#i n c l u d e <i o s t r e a m > u s i n g s t d : :c o u t; #i n c l u d e " C o m m i s s i o n E m p l o y e e . h " // construtor C o m m i s s i o n E m p l o y e e : : C o m m i s s i o n E m p l o y e e (c o n s t s t r i n g & f i r s t , c o n s t s t r i n g &l a s t , c o n s t s t r i n g &s s n , d o u b l e s a l e s , d o u b l e r a t e ) : E m p l o y e e ( f i r s t , l a s t , s s n ) { s e t G r o s s S a l e s ( s a l e s ) ; s e t C o m m i s s i o n R a t e ( r a t e ) ; } // fim do construtor CommissionEmployee

(95)

ComissionEmployee.cpp (cont.)

// calcula os rendimentos;

// sobrescreve a fun¸c˜ao virtual pura earnings em Employee

d o u b l e C o m m i s s i o n E m p l o y e e : : e a r n i n g s ( ) c o n s t

{

r e t u r n g e t C o m m i s s i o n R a t e ( ) ∗ g e t G r o s s S a l e s ( ) ; } // fim da fun¸c˜ao earnings

// imprime informa¸c˜oes do CommissionEmployee

v o i d C o m m i s s i o n E m p l o y e e : : p r i n t ( ) c o n s t { c o u t << " commission employee : " ; E m p l o y e e : : p r i n t ( ) ; // reutiliza¸c˜ao de c´odigo c o u t << " \ ngross sales : " << g e t G r o s s S a l e s ( ) << " ; commission rate : " << g e t C o m m i s s i o n R a t e ( ) ;

(96)

#i f n d e f BASEPLUS H

#d e f i n e BASEPLUS H

#i n c l u d e " C o m m i s s i o n E m p l o y e e . h "

c l a s s B a s e P l u s C o m m i s s i o n E m p l o y e e :

p u b l i c C o m m i s s i o n E m p l o y e e {

d o u b l e b a s e S a l a r y ; // sal´ario-base por semana

p u b l i c:

B a s e P l u s C o m m i s s i o n E m p l o y e e ( c o n s t s t r i n g &=" " ,

c o n s t s t r i n g &=" " , c o n s t s t r i n g &=" " , d o u b l e = 0 . 0 ,

d o u b l e = 0 . 0 , d o u b l e = 0 . 0 ) ;

v o i d s e t B a s e S a l a r y ( d o u b l e ) ; // configura o sal´ario-base

d o u b l e g e t B a s e S a l a r y ( ) c o n s t; // retorna o sal´ario-base // palavra-chave virtual assinala inten¸c˜ao de sobrescrever

v i r t u a l d o u b l e e a r n i n g s ( ) c o n s t; // calcula os rendimentos

v i r t u a l v o i d p r i n t ( ) c o n s t; // imprime o objeto BasePlusCom-missionEmployee

(97)

BasePlusComissionEmployee.cpp

#i n c l u d e <i o s t r e a m >

u s i n g s t d : :c o u t;

// Defini¸c˜ao da classe BasePlusCommissionEmployee

#i n c l u d e " B a s e P l u s C o m m i s s i o n E m p l o y e e . h " // construtor B a s e P l u s C o m m i s s i o n E m p l o y e e : : B a s e P l u s C o m m i s s i o n E m p l o y e e ( c o n s t s t r i n g & f i r s t , c o n s t s t r i n g &l a s t , c o n s t s t r i n g &s s n , d o u b l e s a l e s , d o u b l e r a t e , d o u b l e s a l a r y ) : C o m m i s s i o n E m p l o y e e ( f i r s t , l a s t , s s n , s a l e s , r a t e ) {

(98)

// calcula os rendimentos;

// sobrescreve a fun¸c˜ao virtual pura earnings em Employee

d o u b l e B a s e P l u s C o m m i s s i o n E m p l o y e e : : e a r n i n g s ( ) c o n s t

{

r e t u r n g e t B a s e S a l a r y ( ) +

C o m m i s s i o n E m p l o y e e : : e a r n i n g s ( ) ; } // fim da fun¸c˜ao earnings

// imprime informa¸c˜oes de BasePlusCommissionEmployee

v o i d B a s e P l u s C o m m i s s i o n E m p l o y e e : : p r i n t ( ) c o n s t

{

c o u t << " base - salaried " ;

C o m m i s s i o n E m p l o y e e : : p r i n t ( ) ; // reutiliza¸c˜ao de c´odigo

c o u t << " ; base salary : " << g e t B a s e S a l a r y ( ) ; } // fim da fun¸c˜ao print

(99)

Main.cpp

#i n c l u d e <i o s t r e a m >

#i n c l u d e <i o m a n i p >

u s i n g n a m e s p a c e s t d ;

#i n c l u d e <v e c t o r >

// inclui defini¸c˜oes de classes na hierarquia Employee

#i n c l u d e " Employee . h " #i n c l u d e " S a l a r i e d E m p l o y e e . h " #i n c l u d e " H o u r l y E m p l o y e e . h " #i n c l u d e " C o m m i s s i o n E m p l o y e e . h " #i n c l u d e " B a s e P l u s C o m m i s s i o n E m p l o y e e . h " v o i d v i r t u a l V i a P o i n t e r (c o n s t E m p l o y e e ∗ c o n s t) ; // prot´otipo

(100)

i n t main ( ) {

// configura a formata¸c˜ao de sa´ıda de ponto flutuante

c o u t << f i x e d << s e t p r e c i s i o n ( 2 ) ;

// cria objetos da classe derivada

S a l a r i e d E m p l o y e e s a l a r i e d E m p l o y e e ( " John " , " Smith " , " 111 -11 -1111 " , 800 ) ; H o u r l y E m p l o y e e h o u r l y E m p l o y e e ( " Karen " , " Price " , " 222 -22 -2222 " , 1 6 . 7 5 , 40 ) ; C o m m i s s i o n E m p l o y e e c o m m i s s i o n E m p l o y e e ( " Sue " , " Jones " , " 333 -33 -3333 " , 1 0 0 0 0 , . 0 6 ) ; B a s e P l u s C o m m i s s i o n E m p l o y e e b a s e P l u s C o m m i s s i o n E m p l o y e e ( " Bob " , " Lewis " , " 444 -44 -4444 " , 5 0 0 0 , . 0 4 , 300 ) ; . . .

(101)

Main.cpp (cont.)

c o u t << " Employees processed individually using static binding :\ n \ n " ;

// sa´ıda de info. e rendimentos dos Employees com vincula¸c˜ao est´atica

s a l a r i e d E m p l o y e e . p r i n t ( ) ; c o u t << " \ nearned $" << s a l a r i e d E m p l o y e e . e a r n i n g s ( ) ; h o u r l y E m p l o y e e . p r i n t ( ) ; c o u t << " \ nearned $" << h o u r l y E m p l o y e e . e a r n i n g s ( ) ; c o m m i s s i o n E m p l o y e e . p r i n t ( ) ; c o u t << " \ nearned $" << c o m m i s s i o n E m p l o y e e . e a r n i n g s ( ) ; b a s e P l u s C o m m i s s i o n E m p l o y e e . p r i n t ( ) ; c o u t << " \ nearned $" ’ << b a s e P l u s C o m m i s s i o n E m p l o y e e . earnings ();

(102)

// cria um vector a partir dos quatro ponteiros da classe b´asica

v e c t o r < E m p l o y e e ∗ > e m p l o y e e s ( 4 ) ;

// inicializa o vector com Employees

e m p l o y e e s [ 0 ] = &s a l a r i e d E m p l o y e e ; e m p l o y e e s [ 1 ] = &h o u r l y E m p l o y e e ; e m p l o y e e s [ 2 ] = &c o m m i s s i o n E m p l o y e e ;

e m p l o y e e s [ 3 ] = &b a s e P l u s C o m m i s s i o n E m p l o y e e ;

c o u t << " Employees processed polymorphically via dynamic binding :\ n \ n " ;

(103)

Main.cpp (cont.)

// chama virtualViaPointer para imprimir informa¸c˜oes e rendimentos // de cada Employee utilizando vincula¸c˜ao dinˆamica

c o u t << " Virtual function calls made off base - class pointers :\ n \ n " ;

f o r ( s i z e t i = 0 ; i < e m p l o y e e s . s i z e ( ) ; i++ ) v i r t u a l V i a P o i n t e r ( e m p l o y e e s [ i ] ) ;

// chama virtualViaReference para imprimir informa¸c˜oes // de cada Employee utilizando vincula¸c˜ao dinˆamica

c o u t << " Virtual function calls made off base - class re fer enc es :\ n \ n " ;

f o r ( s i z e t i = 0 ; i < e m p l o y e e s . s i z e ( ) ; i++ )

// observe o desreferenciamento

(104)

// chama fun¸c˜oes print e earnings virtual de Employee a partir de um // ponteiro de classe b´asica utilizando vincula¸c˜ao dinˆamica

v o i d v i r t u a l V i a P o i n t e r (c o n s t E m p l o y e e ∗ c o n s t b a s e C l a s s P t r ) {

b a s e C l a s s P t r −>p r i n t ( ) ;

c o u t << " \ nearned $" << b a s e C l a s s P t r −>e a r n i n g s ( ) ; } // fim da fun¸c˜ao virtualViaPointer

// chama fun¸c˜oes print e earnings virtual de Employee a partir de um // referˆencia de classe b´asica utilizando vincula¸c˜ao dinˆamica

v o i d v i r t u a l V i a R e f e r e n c e ( c o n s t E m p l o y e e &b a s e C l a s s R e f ) {

b a s e C l a s s R e f . p r i n t ( ) ;

c o u t << " \ nearned $" << b a s e C l a s s R e f . e a r n i n g s ( ) ; } // fim da fun¸c˜ao virtualViaReference

(105)

Referências

Documentos relacionados

A abertura de vagas de estágios nas empresas do setor eletro-eletrônico, instaladas na Zona Franca de Manaus-AM, que passaram a responder pela maior parte dos estágios na área

O Procedimento está relacionado com questões que decorrem do Contrato de Compra de Ações celebrado pela subsidiária Mandala Empreendimentos e Participações S.A. Os

Cozaar Comp é indicado para o tratamento da hipertensão essencial em doentes cuja pressão arterial não está controlada de forma adequada com losartan ou

Os nanomateriais sintetizados foram aplicados na fotocatálise de corantes orgânicos a modo de verificar a atividade fotocatalítica e a capacidade de adsorção de cada material. Para o

Quando o diálogo Expert Level Parameter aparecer, selecione Variable Selection, , então a seguinte caixa de diálogo aparecerá:... Este diálogo também pode ser acessado através

Semelhante ao trabalho de Mezadri et al., 2011, observamos que a FLX administrada aos ratos do grupo AP, foi capaz de bloquear os efeitos da reexposição ao nado forçado

Mudanças nas actuais abordagens ao sector cultural e criativo vêm exigindo novas orientações para as políticas culturais (uma política cultural criativa para

O catalisador de níquel é um exemplo de catalisador suportado que tem sido fortemente pesquisado devido à sua elevada atividade e estabilidade em relação ao