11.6 Duck Typing
Uma característica de linguagens dinâmicas como Python é a chamada Duck Typing, a tipagem de pato. É uma característica de um sistema de tipos em que a semântica de uma classe é determinada pela sua capacidade de responder a alguma mensagem, ou seja, responder a determinado atributo (ou método). O exemplo canônico (e a razão do nome) é o teste do pato: se ele se parece com um pato, nada como um pato e grasna como um pato, então provavelmente é um pato.
Veja o exemplo abaixo:
class Pato:
python
def grasna(self): print('quack!')
python
class Ganso:
python
def grasna(self): print('quack!')
python
if name == ' main ': pato = Pato() print(pato.grasna())ganso = Ganso() print(ganso.grasna())
Que gera a saída:
quack! quack!
Você deve escrever o código esperando somente uma interface do objeto, não um tipo de objeto. No caso da nossa classe ControleDeBonificacoes , o método registra() espera um objeto que possua o método get_bonificacao() e não apenas um funcionário.
O Duck Typing é um estilo de programação que não procura o tipo do objeto para determinar se ele tem a interface correta. Ao invés disso, o método ou atributo é simplesmente chamado ou usado (‘se parece como um pato e grasna como um pato, então deve ser um pato’). Duck Typing evita testes usando as funções type() , isinstance() e até mesmo a hasattr() - ao invés disso, deixa o erro estourar na frente do programador.
A maneira Pythônica para garantir a consistência do sistema não é verificar os tipos e atributos de um objeto, mas pressupor a existência do atributo no objeto e tratar uma exceção, caso ocorra, através do comando try/except :
try:
self._total_bonificacoes += obj.get_bonificacao() except AttributeError as e:
java
print(e)Estamos pedindo ao interpretador para tentar executar a linha de código dentro do comando try
(tentar). Caso ocorra algum erro, ele vai tratar este erro com o comando except e executar algo, como
imprimir o erro (similar ao exemplo). Não se preocupe de entender os detalhes sobre este código e o uso dotry/except neste momento, teremos um capítulo só para falar deles.
O que é importante é que a maneira pythônica de se fazer é assumir a existência do atributo e capturar (tratar) um exceção quando o atributo não pertencer ao objeto e seguir o fluxo do programa. Por ora, faremos esta checagem utilizando a função hasattr() .
HERANÇA VERSUS ACOPLAMENTO
Note que o uso de herança aumenta o acoplamento entre as classes, isto é, o quanto uma classe depende de outra. A relação entre classe mãe e filha é muito forte e isso acaba fazendo com que o programador das classes filhas tenha que conhecer a implementação da classe mãe e vice-versa - fica difícil fazer uma mudança pontual no sistema.
Por exemplo, imagine se tivermos que mudar algo na nossa classe Funcionario , mas não quiséssemos que todos os funcionários sofressem a mesma mudança. Precisaríamos passar por cada uma das filhas de Funcionario verificando se ela se comporta como deveria ou se devemos sobrescrever o tal método modificado.
Esse é um problema da herança, e não do polimorfismo, que resolveremos mais tarde.