Menu
Coddy logo textTech

Classes e Métodos Abstratos

Parte da seção Object Oriented Programming do Journey de Python da Coddy — lição 25 de 64.

Classes abstratas são classes que não podem ser instanciadas diretamente e contêm métodos abstratos que devem ser implementados por subclasses.

Pense nisso como um formulário: Uma classe abstrata é como um código de formulário obrigatório onde alguns campos são exigidos (métodos abstratos) e outros são opcionais (métodos concretos). Você não pode enviar o formulário em si - você deve preencher todos os campos obrigatórios primeiro. Da mesma forma, você não pode criar instâncias de uma classe abstrata até que todos os métodos abstratos sejam implementados em uma subclasse.

Importe o módulo abc para criar classes abstratas:

from abc import ABC, abstractmethod

Crie uma classe abstrata com métodos abstratos:

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def perimeter(self):
        pass
    
    def describe(self):
        return "This is a shape"  # Método concreto (possui implementação)

O decorador @abstractmethod marca métodos que devem ser implementados por subclasses - estes são os "campos obrigatórios" no seu formulário. Métodos regulares como describe() podem ter implementações e são herdados como estão - estes são os "campos pré-preenchidos".

Por que usar classes abstratas? Elas impõem um contrato. Se você criar uma classe Shape, você está dizendo "toda forma DEVE ser capaz de calcular sua área e perímetro". Isso evita bugs onde você pode esquecer de implementar métodos críticos.

Tente criar uma instância da classe abstrata:

# Isso causará um erro:
# shape = Shape()  # TypeError: Não é possível instanciar a classe abstrata

Este erro é intencional - é como tentar enviar um formulário vazio. O Python está dizendo "Você ainda não preencheu os campos obrigatórios (métodos area e perimeter)!"

Crie uma subclasse concreta que implemente todos os métodos abstratos:

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2
    
    def perimeter(self):
        return 2 * 3.14 * self.radius

Agora nós "preenchemos todos os campos obrigatórios" - implementamos tanto area() quanto perimeter(). A classe Circle agora é uma classe concreta completa que pode ser instanciada.

Agora você pode criar instâncias da classe concreta:

circle = Circle(5)
print(circle.area())
print(circle.perimeter())
print(circle.describe())  # Método concreto herdado

Crie outra subclasse concreta:

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width  self.height
    
    def perimeter(self):
        return 2 * (self.width + self.height)

rectangle = Rectangle(4, 6)
print(rectangle.area())
print(rectangle.perimeter())

Saída:

78.5
31.400000000000002
This is a shape
24
20

Classes abstratas definem um contrato que as subclasses devem seguir. Use ABC e @abstractmethod para criar classes abstratas. As subclasses devem implementar todos os métodos abstratos ou elas também serão abstratas. Isso garante consistência e evita implementações incompletas.

challenge icon

Desafio

Médio

Neste desafio, você implementará um sistema de processamento de pagamentos.

Você precisa completar a implementação nestes arquivos:

  • paymentmethod.py - Classe base abstrata com lógica de validação
  • creditcard.py - Implementação de pagamento por cartão de crédito
  • paypal.py - Implementação de pagamento por PayPal

Siga os comentários TODO em cada arquivo para implementar a funcionalidade necessária. Os comentários o guiarão passo a passo na criação de métodos abstratos, na implementação de subclasses concretas e no estabelecimento de relações de importação adequadas entre os arquivos.

O arquivo driver.py contém casos de teste que verificarão se sua implementação funciona corretamente, processando diferentes cenários de pagamento e exibindo os detalhes apropriados para cada método de pagamento.

Folha de consulta

Classes abstratas não podem ser instanciadas diretamente e contêm métodos abstratos que devem ser implementados por subclasses.

Importe o módulo abc:

from abc import ABC, abstractmethod

Crie uma classe abstrata com métodos abstratos:

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def perimeter(self):
        pass
    
    def describe(self):
        return "This is a shape"  # Método concreto (possui implementação)

O decorador @abstractmethod marca métodos que devem ser implementados por subclasses. Métodos regulares podem ter implementações.

Classes abstratas não podem ser instanciadas:

# Isso causará um erro:
# shape = Shape()  # TypeError: Can't instantiate abstract class

Crie subclasses concretas que implementem todos os métodos abstratos:

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2
    
    def perimeter(self):
        return 2 * 3.14 * self.radius

circle = Circle(5)
print(circle.area())        # 78.5
print(circle.describe())    # Método concreto herdado

Ponto Chave: Classes abstratas definem um modelo que as subclasses devem seguir. As subclasses devem implementar todos os métodos abstratos ou também serão abstratas.

Experimente você mesmo

from creditcard import CreditCard
from paypal import PayPal

# Teste as implementações - NÃO MODIFIQUE ESTE CÓDIGO DE TESTE
cc = CreditCard("1234567890123456")
pp = PayPal("user@example.com")

# Processar pagamentos válidos
if cc.validate(100):
    print(cc.process_payment(100))
    print(cc.payment_details())

if pp.validate(200):
    print(pp.process_payment(200))
    print(pp.payment_details())

# Tentar um valor inválido
if not pp.validate(0):
    print("Invalid payment amount")

# Isso geraria um erro se fosse descomentado:
# pm = PaymentMethod()  # Não é possível instanciar uma classe abstrata
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Object Oriented Programming