Skip to content

    Chapter 30, Intermediate

    Abstraction with ABC

    An abstract class defines a contract that subclasses are required to fulfill. It's a way of saying "any class that does X needs to have these methods".

    Code for this chapter: intermediario/cap30_abstracao.py

    The contract

    The module abc provides ABC and @abstractmethod. A class with abstract methods cannot be instantiated. Subclasses need to implement all of them:

    intermediario/cap30_abstracao.pylinhas 10 a 40
    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())
    
    Output
    Circulo com área 3.14
    Quadrado com área 4.00
    

    The method descrever is concrete and uses the area abstract: the base class writes the algorithm and the subclasses fill in the gaps. This pattern (template method) is one of the most useful uses of abstract classes.

    The error comes early

    The difference from the NotImplementedError in the previous chapter is when where the error appears. With ABC, trying to create an incomplete object fails at creation, and not just when the missing method is called:

    intermediario/cap30_abstracao.pylinhas 45 a 58
    try:
        Forma()
    except TypeError as erro:
        print(erro)
    
    
    class Incompleta(Forma):
        pass
    
    
    try:
        Incompleta()
    except TypeError as erro:
        print(erro)
    
    Output
    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'
    

    Abstraction and encapsulation are not the same thing

    ConceptQuestion it answersTool in Python
    EncapsulationWhat do I hide or protect inside the object?Convention _nome and @property
    AbstractionWhat does any implementation need to offer?ABC and @abstractmethod

    And what about duck typing?

    You don't need ABC for polymorphism to work. I use abstract classes when there is a family of implementations with common behavior (the mold method). When only the shape of the object matters, the lighter tool is typing.Protocol, which I show at the advanced level.

    Exercise 1

    Notifiers

    Create the abstract class Notificador with the method enviar(mensagem), the implementations Email and SMS (that return the text "email: ..." and "sms: ...") and the function avisar(notificadores, mensagem) that returns the list of results.