Capítulo 30, Intermediário
Abstração com ABC
Uma classe abstrata define um contrato que as filhas são obrigadas a cumprir. É o jeito de dizer "qualquer classe que faça X precisa ter estes métodos".
Código deste capítulo: intermediario/cap30_abstracao.py
O contrato
O módulo abc oferece ABC e @abstractmethod. Uma classe com métodos abstratos não pode ser instanciada. As subclasses precisam implementar todos eles:
from abc import ABC, abstractmethod
import math
class Forma(ABC):
@abstractmethod
def area(self):
...
def descrever(self):
return f"{type(self).__name__} com área {self.area():.2f}"
class Circulo(Forma):
def __init__(self, raio):
self.raio = raio
def area(self):
return math.pi * self.raio ** 2
class Quadrado(Forma):
def __init__(self, lado):
self.lado = lado
def area(self):
return self.lado ** 2
for forma in (Circulo(1), Quadrado(2)):
print(forma.descrever())
Circulo com área 3.14
Quadrado com área 4.00
O método descrever é concreto e usa o area abstrato: a classe base escreve o algoritmo e as filhas preenchem as lacunas. Esse padrão (método molde) é um dos usos mais úteis de classes abstratas.
O erro vem cedo
A diferença para o NotImplementedError do capítulo anterior é quando o erro aparece. Com ABC, tentar criar um objeto incompleto falha na criação, e não só quando o método ausente for chamado:
try:
Forma()
except TypeError as erro:
print(erro)
class Incompleta(Forma):
pass
try:
Incompleta()
except TypeError as erro:
print(erro)
Can't instantiate abstract class Forma without an implementation for abstract method 'area'
Can't instantiate abstract class Incompleta without an implementation for abstract method 'area'
Abstração e encapsulamento não são a mesma coisa
| Conceito | Pergunta que responde | Ferramenta em Python |
|---|---|---|
| Encapsulamento | O que eu escondo ou protejo dentro do objeto? | Convenção _nome e @property |
| Abstração | O que qualquer implementação precisa oferecer? | ABC e @abstractmethod |
E o duck typing?
Você não precisa de
ABCpara o polimorfismo funcionar. Eu uso classes abstratas quando existe uma família de implementações com comportamento comum (o método molde). Quando só importa a forma do objeto, a ferramenta mais leve étyping.Protocol, que mostro no nível avançado.
Exercício 1
Notificadores
Crie a classe abstrata Notificador com o método enviar(mensagem), as implementações Email e SMS (que devolvem o texto "email: ..." e "sms: ...") e a função avisar(notificadores, mensagem) que devolve a lista de resultados.