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.


⬅️ Capítulo Anterior | Próximo Capítulo ➡️