Menu
Coddy logo textTech

Clases y métodos abstractos

Parte de la sección Object Oriented Programming del Journey de Python de Coddy — lección 25 de 64.

Las clases abstractas son clases que no se pueden instanciar directamente y contienen métodos abstractos que deben ser implementados por las subclases.

Piénselo como un formulario: Una clase abstracta es como el código de un formulario obligatorio donde algunos campos son requeridos (métodos abstractos) y otros son opcionales (métodos concretos). No puede enviar el formulario en sí; primero debe completar todos los campos obligatorios. De manera similar, no puede crear instancias de una clase abstracta hasta que todos los métodos abstractos se implementen en una subclase.

Importa el módulo abc para crear clases abstractas:

from abc import ABC, abstractmethod

Crea una clase abstracta con métodos abstractos:

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def perimeter(self):
        pass
    
    def describe(self):
        return "This is a shape"  # Método concreto (tiene implementación)

El decorador @abstractmethod marca los métodos que deben ser implementados por las subclases; estos son los "campos obligatorios" de su formulario. Los métodos regulares como describe() pueden tener implementaciones y se heredan tal cual; estos son los "campos pre-completados".

¿Por qué usar clases abstractas? Obligan a cumplir un contrato. Si creas una clase Shape, estás diciendo "cada forma DEBE ser capaz de calcular su área y perímetro". Esto evita errores donde podrías olvidar implementar métodos críticos.

Intenta crear una instancia de la clase abstracta:

# Esto causará un error:
# shape = Shape()  # TypeError: Can't instantiate abstract class

Este error es intencional; es como intentar enviar un formulario vacío. ¡Python está diciendo "Aún no has completado los campos obligatorios (métodos area y perimeter)!"

Crea una subclase concreta que implemente todos los métodos abstractos:

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

Ahora hemos "completado todos los campos requeridos": hemos implementado tanto area() como perimeter(). La clase Circle es ahora una clase concreta y completa que puede ser instanciada.

Ahora puedes crear instancias de la clase concreta:

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

Crea otra subclase 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())

Salida:

78.5
31.400000000000002
This is a shape
24
20

Las clases abstractas definen un contrato que las subclases deben seguir. Utiliza ABC y @abstractmethod para crear clases abstractas. Las subclases deben implementar todos los métodos abstractos o también serán abstractas. Esto garantiza la consistencia y evita implementaciones incompletas.

challenge icon

Desafío

Intermedio

En este desafío, implementarás un sistema de procesamiento de pagos.

Debes completar la implementación en estos archivos:

  • paymentmethod.py - Clase base abstracta con lógica de validación
  • creditcard.py - Implementación de pago con tarjeta de crédito
  • paypal.py - Implementación de pago con PayPal

Sigue los comentarios TODO en cada archivo para implementar la funcionalidad requerida. Los comentarios te guiarán paso a paso a través de la creación de métodos abstractos, la implementación de subclases concretas y el establecimiento de relaciones de importación adecuadas entre los archivos.

El archivo driver.py contiene casos de prueba que verificarán que tu implementación funcione correctamente, procesando diferentes escenarios de pago y mostrando los detalles apropiados para cada método de pago.

Hoja de referencia

Las clases abstractas no pueden instanciarse directamente y contienen métodos abstractos que deben ser implementados por las subclases.

Importa el módulo abc:

from abc import ABC, abstractmethod

Crea una clase abstracta con métodos abstractos:

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def perimeter(self):
        pass
    
    def describe(self):
        return "This is a shape"  # Método concreto (tiene implementación)

El decorador @abstractmethod marca los métodos que deben ser implementados por las subclases. Los métodos regulares pueden tener implementaciones.

Las clases abstractas no pueden instanciarse:

# Esto causará un error:
# shape = Shape()  # TypeError: Can't instantiate abstract class

Crea subclases concretas que implementen todos los métodos abstractos:

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 heredado

Punto clave: Las clases abstractas definen una plantilla que las subclases deben seguir. Las subclases deben implementar todos los métodos abstractos o también serán abstractas.

Pruébalo tú mismo

from creditcard import CreditCard
from paypal import PayPal

# Probar las implementaciones - NO MODIFICAR ESTE CÓDIGO DE PRUEBA
cc = CreditCard("1234567890123456")
pp = PayPal("user@example.com")

# Procesar pagos 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())

# Probar un monto no válido
if not pp.validate(0):
    print("Invalid payment amount")

# Esto generaría un error si se descomentara:
# pm = PaymentMethod()  # No se puede instanciar una clase abstracta
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Object Oriented Programming