Curso de Programación Orientada a Objetos

Curso de Programación Orientada a Objetos
Guía didáctica en 10 lecciones
por Daniel Caraballo
danielcaraballo.es
Índice
1. Clases en Programación Orientada a Objetos
¿Qué es una clase?
Una clase es un molde o plantilla que define cómo serán los objetos.
Dentro de una clase se definen:
- Atributos (datos)
- Métodos (acciones)
Es como un plano que describe cómo construir algo.
Ejemplo de una clase en Python
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre # Atributo
self.edad = edad # Atributo
def saludar(self): # Método
return f"Hola, soy {self.nombre}"
2. Objetos en Programación Orientada a Objetos
¿Qué es un objeto?
Un objeto es una instancia de una clase.
Si la clase es un plano, el objeto es la casa construida con ese plano.
Características de un objeto
- Atributos: datos propios del objeto.
- Métodos: acciones que puede realizar.
- Estado: cómo se encuentra en un momento dado.
- Identidad: cada objeto es único en memoria.
Ejemplo de creación de objetos
class Persona:
def __init__(self, nombre, edad):
self.nombre = nombre
self.edad = edad
# Creamos dos objetos distintos
persona1 = Persona("Ana", 30)
persona2 = Persona("Luis", 25)
print(persona1.nombre) # Ana
print(persona2.nombre) # Luis
3. Atributos y Métodos
¿Qué son los atributos?
Los atributos son las características o datos que tiene un objeto.
Por ejemplo, una persona puede tener:
- nombre
- edad
- altura
Cada objeto tendrá sus propios valores para esos atributos.
¿Qué son los métodos?
Los métodos son las acciones que un objeto puede realizar.
Siguiendo el ejemplo de una persona:
- saludar()
- caminar()
- hablar()
Los métodos son funciones que viven dentro de una clase.
Ejemplo de atributos y métodos en Python
class Coche:
def __init__(self, marca, velocidad):
self.marca = marca # Atributo
self.velocidad = velocidad # Atributo
def acelerar(self): # Método
self.velocidad += 10
return f"Velocidad actual: {self.velocidad} km/h"
# Creamos un objeto
mi_coche = Coche("Toyota", 120)
print(mi_coche.acelerar()) # Velocidad actual: 130 km/h
4. Abstracción
¿Qué es la abstracción?
La abstracción consiste en centrarse solo en lo importante y ocultar los detalles innecesarios.
Es como usar un coche: no necesitas saber cómo funciona el motor, solo cómo conducirlo.
Ejemplo de abstracción en Python
class Cafetera:
def __init__(self):
self.agua = 100
def hacer_cafe(self):
# El usuario no ve estos detalles internos
self.agua -= 10
return "Café listo"
# El usuario solo usa el método, sin saber cómo funciona dentro
cafetera = Cafetera()
print(cafetera.hacer_cafe())
¿Por qué es útil la abstracción?
- Crear código más simple de usar
- Ocultar detalles complejos
- Evitar errores del usuario
- Reutilizar componentes sin conocer su interior
5. Encapsulamiento
¿Qué es el encapsulamiento?
El encapsulamiento consiste en proteger los datos internos de un objeto para evitar que sean modificados directamente desde fuera.
Es como una caja fuerte: solo se accede a ella mediante métodos.
Modificadores de acceso en Python
Python usa una convención:
atributo→ público_atributo→ protegido__atributo→ privado
Ejemplo de encapsulamiento en Python
class CuentaBancaria:
def __init__(self, saldo):
self.__saldo = saldo # Atributo privado
def depositar(self, cantidad):
self.__saldo += cantidad
def obtener_saldo(self):
return self.__saldo
cuenta = CuentaBancaria(100)
cuenta.depositar(50)
print(cuenta.obtener_saldo()) # 150
6. Herencia
¿Qué es la herencia?
La herencia permite crear nuevas clases basadas en clases existentes.
La clase hija hereda atributos y métodos de la clase padre.
Ventajas de la herencia
- Reutilizar código
- Evitar duplicación
- Crear jerarquías lógicas
- Extender funcionalidades fácilmente
Ejemplo de herencia en Python
class Animal:
def __init__(self, nombre):
self.nombre = nombre
def hacer_sonido(self):
return "Sonido genérico"
# Clase hija que hereda de Animal
class Perro(Animal):
def hacer_sonido(self):
return "Guau!"
mi_perro = Perro("Toby")
print(mi_perro.nombre) # Toby
print(mi_perro.hacer_sonido()) # Guau!
7. Polimorfismo
¿Qué es el polimorfismo?
El polimorfismo permite que diferentes clases respondan al mismo método, pero cada una a su manera.
Por ejemplo:
- Perro.hacer_sonido() → «Guau»
- Gato.hacer_sonido() → «Miau»
Ventajas del polimorfismo
- Escribir código más flexible
- Reutilizar funciones que aceptan distintos tipos
- Evitar condicionales innecesarios
- Extender comportamientos sin modificar código existente
Ejemplo de polimorfismo en Python
class Animal:
def hacer_sonido(self):
return "Sonido genérico"
class Perro(Animal):
def hacer_sonido(self):
return "Guau!"
class Gato(Animal):
def hacer_sonido(self):
return "Miau!"
# Función que usa polimorfismo
def reproducir_sonido(animal):
print(animal.hacer_sonido())
reproducir_sonido(Perro()) # Guau!
reproducir_sonido(Gato()) # Miau!
8. Clases Abstractas
¿Qué es una clase abstracta?
Una clase abstracta es una clase que no se puede instanciar directamente.
Sirve como modelo para otras clases y define métodos que las clases hijas deben implementar.
¿Para qué sirve una clase abstracta?
- Definir una estructura común
- Obligar a las clases hijas a implementar ciertos métodos
- Evitar instanciar clases incompletas
- Organizar jerarquías más claras
Ejemplo de clase abstracta en Python
from abc import ABC, abstractmethod
# Clase abstracta
class Animal(ABC):
@abstractmethod
def hacer_sonido(self):
pass
# Clase hija que implementa el método abstracto
class Perro(Animal):
def hacer_sonido(self):
return "Guau!"
mi_perro = Perro()
print(mi_perro.hacer_sonido()) # Guau!
9. Principios SOLID
¿Qué es SOLID?
SOLID es un conjunto de 5 principios que ayudan a escribir código más limpio, mantenible y escalable.
- S — Single Responsibility Principle
- O — Open/Closed Principle
- L — Liskov Substitution Principle
- I — Interface Segregation Principle
- D — Dependency Inversion Principle
S — Principio de Responsabilidad Única
Una clase debe tener una sola razón para cambiar.
O — Principio Abierto/Cerrado
Una clase debe estar abierta a extensión y cerrada a modificación.
L — Principio de Sustitución de Liskov
Una clase hija debe poder sustituir a su clase padre sin romper el programa.
I — Principio de Segregación de Interfaces
Es mejor tener muchas interfaces pequeñas que una grande.
D — Principio de Inversión de Dependencias
Las clases deben depender de abstracciones, no de implementaciones concretas.
Ejemplo simple de SOLID en Python
# Ejemplo del principio S (Responsabilidad Única)
class Reporte:
def generar(self):
return "Datos del reporte"
class ReportePrinter:
def imprimir(self, reporte):
print(reporte.generar())
printer = ReportePrinter()
printer.imprimir(Reporte())
10. Patrones de Diseño
¿Qué son los patrones de diseño?
Los patrones de diseño son soluciones reutilizables a problemas comunes en el desarrollo de software.
No son código exacto, sino modelos que puedes adaptar.
Se dividen en:
- Creacionales — cómo crear objetos
- Estructurales — cómo organizar clases
- Comportamiento — cómo interactúan los objetos
Patrones Creacionales
- Singleton — solo una instancia
- Factory Method — crea objetos sin especificar la clase exacta
- Builder — construye objetos paso a paso
# Ejemplo simple de Singleton en Python
class Config:
_instancia = None
def __new__(cls):
if cls._instancia is None:
cls._instancia = super().__new__(cls)
return cls._instancia
c1 = Config()
c2 = Config()
print(c1 is c2) # True
Patrones Estructurales
- Adapter — adapta una interfaz a otra
- Decorator — añade funcionalidades sin modificar la clase
- Facade — simplifica sistemas complejos
# Ejemplo simple de Decorator
def mayusculas(func):
def wrapper():
return func().upper()
return wrapper
@mayusculas
def saludar():
return "hola"
print(saludar()) # HOLA
Patrones de Comportamiento
- Observer — notifica cambios a múltiples objetos
- Strategy — intercambia algoritmos fácilmente
- Command — encapsula acciones como objetos
# Ejemplo simple de Strategy
class EstrategiaA:
def ejecutar(self):
return "Estrategia A"
class EstrategiaB:
def ejecutar(self):
return "Estrategia B"
class Contexto:
def __init__(self, estrategia):
self.estrategia = estrategia
def operar(self):
return self.estrategia.ejecutar()
ctx = Contexto(EstrategiaA())
print(ctx.operar()) # Estrategia A