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, abstractmethodCrea 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 classEste 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.radiusAhora 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 heredadoCrea 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
20Las 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.
Desafío
IntermedioEn 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óncreditcard.py- Implementación de pago con tarjeta de créditopaypal.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, abstractmethodCrea 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 classCrea 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 heredadoPunto 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 abstractaEsta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
1Fundamentos de la POO
Archivos externosIntroducción a la POOClases vs ObjetosEl parámetro selfMétodosAtributosMétodo constructor (__init__)Resumen - Calculadora simple4Herencia
Herencia básicaLa función super()Sobrescritura de métodosHerencia múltipleOrden de resolución de métodosResumen - Jerarquía de empleados7Métodos especiales
Introducción a los métodos mágicosSobrecarga de operadoresMétodos mágicos de contenedoresRepaso - Lista personalizada10Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy2Decoradores
Introducción a los decoradoresDecorador propertyDecorador de métodos estáticosDecorador de métodos de clase5Polimorfismo
Sobreescritura de métodos revisitadaDuck TypingClases y métodos abstractosDiseño de interfacesResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaMixinsMétodos estáticos y de claseDecoradores de claseGestores de contexto11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Propiedades de clase
Variables de instancia vs de claseDecoradores de propiedadesAtributos privadosResumen - Gestor de cuentas bancarias