11. Programación Orientada a Objetos
🎯 11.1 ¿Qué es la POO y por qué se usa?
Section titled “🎯 11.1 ¿Qué es la POO y por qué se usa?”Concepto de POO
Section titled “Concepto de POO”La Programación Orientada a Objetos (POO) es un paradigma de programación que organiza el código en torno a “objetos” que representan entidades del mundo real o conceptos abstractos. Cada objeto combina datos (atributos) y comportamientos (métodos).
Principios fundamentales
Section titled “Principios fundamentales”| Principio | Descripción |
|---|---|
| Abstracción | Modelar entidades del mundo real en código |
| Encapsulamiento | Ocultar detalles internos, exponer solo lo necesario |
| Herencia | Crear nuevas clases basadas en clases existentes |
| Polimorfismo | Objetos de diferentes clases responden a la misma interfaz |
Ventajas de la POO
Section titled “Ventajas de la POO”- Reutilización: Código modular y reutilizable
- Mantenibilidad: Cambios localizados, fácil de actualizar
- Organización: Estructura clara y lógica
- Modelado natural: Representa conceptos del mundo real
- Escalabilidad: Facilita el crecimiento de proyectos
Conceptos clave
Section titled “Conceptos clave”| Concepto | Descripción |
|---|---|
| Clase | Plantilla o molde para crear objetos |
| Objeto | Instancia específica de una clase |
| Atributo | Datos que describen el objeto |
| Método | Funciones que definen el comportamiento del objeto |
Ejemplo: POO vs Programación Procedural
Section titled “Ejemplo: POO vs Programación Procedural”# PROGRAMACIÓN PROCEDURAL (sin POO)nombre_perro = "Max"edad_perro = 3raza_perro = "Labrador"
def ladrar(nombre): print(f"{nombre} dice: ¡Guau!")
ladrar(nombre_perro)
# PROGRAMACIÓN ORIENTADA A OBJETOSclass Perro: def __init__(self, nombre, edad, raza): self.nombre = nombre self.edad = edad self.raza = raza
def ladrar(self): print(f"{self.nombre} dice: ¡Guau!")
# Crear objetomi_perro = Perro("Max", 3, "Labrador")mi_perro.ladrar() # Max dice: ¡Guau!🏗️ 11.2 Crear clases y objetos en Python
Section titled “🏗️ 11.2 Crear clases y objetos en Python”Definir una clase
Section titled “Definir una clase”Sintaxis:
class NombreClase: # Cuerpo de la clase passCrear objetos (instancias)
Section titled “Crear objetos (instancias)”Sintaxis:
objeto = NombreClase()Convenciones
Section titled “Convenciones”| Convención | Descripción |
|---|---|
| Nombres de clases | PascalCase (primera letra de cada palabra en mayúscula) |
| Nombres de objetos | snake_case (minúsculas con guiones bajos) |
| Indentación | El cuerpo de la clase debe estar indentado |
Ejemplo: Clase básica
Section titled “Ejemplo: Clase básica”# Definir una clase simpleclass Persona: pass
# Crear objetos (instancias)persona1 = Persona()persona2 = Persona()
print(type(persona1)) # <class '__main__.Persona'>print(persona1 == persona2) # False (objetos diferentes)📊 11.3 Propiedades (atributos) y comportamientos (métodos)
Section titled “📊 11.3 Propiedades (atributos) y comportamientos (métodos)”Atributos (propiedades)
Section titled “Atributos (propiedades)”Los atributos son variables que pertenecen a un objeto y almacenan su estado.
Métodos (comportamientos)
Section titled “Métodos (comportamientos)”Los métodos son funciones definidas dentro de una clase que describen el comportamiento del objeto. El primer parámetro siempre es self.
Ejemplo: Atributos y métodos
Section titled “Ejemplo: Atributos y métodos”class Perro: def __init__(self, nombre, raza): self.nombre = nombre # Atributo self.raza = raza # Atributo
def ladrar(self): # Método print(f"{self.nombre} dice: ¡Guau!")
def presentarse(self): # Método print(f"Hola, soy {self.nombre} y soy un {self.raza}")
mi_perro = Perro("Max", "Labrador")mi_perro.ladrar() # Max dice: ¡Guau!mi_perro.presentarse() # Hola, soy Max y soy un Labrador🎬 11.4 El método init() y su función
Section titled “🎬 11.4 El método init() y su función”Concepto de init()
Section titled “Concepto de init()”El método __init__() es el constructor de la clase. Se ejecuta automáticamente cuando se crea un nuevo objeto para inicializar sus atributos.
Sintaxis
Section titled “Sintaxis”def __init__(self, parametros): self.atributo = valorEjemplo: init() básico
Section titled “Ejemplo: init() básico”class Persona: def __init__(self, nombre, edad): self.nombre = nombre self.edad = edad
persona = Persona("Ana", 25)print(f"{persona.nombre} tiene {persona.edad} años")Ejemplo: Con valores por defecto
Section titled “Ejemplo: Con valores por defecto”class CuentaBancaria: def __init__(self, titular, saldo=0): self.titular = titular self.saldo = saldo
def mostrar_saldo(self): print(f"Saldo de {self.titular}: {self.saldo} USD")
cuenta1 = CuentaBancaria("Ana", 1000)cuenta2 = CuentaBancaria("Carlos") # saldo = 0cuenta1.mostrar_saldo() # Saldo de Ana: 1000 USD🔒 11.5 Encapsulamiento y uso de self
Section titled “🔒 11.5 Encapsulamiento y uso de self”self es una referencia al objeto actual. Permite acceder a atributos y métodos del objeto desde dentro de la clase.
Encapsulamiento
Section titled “Encapsulamiento”El encapsulamiento oculta los detalles internos. En Python:
| Nivel | Sintaxis | Descripción |
|---|---|---|
| Público | atributo | Accesible desde cualquier lugar |
| Protegido | _atributo | Convención, no debería accederse externamente |
| Privado | __atributo | Name mangling, difícil de acceder externamente |
Ejemplo: Uso de self
Section titled “Ejemplo: Uso de self”class Rectangulo: def __init__(self, base, altura): self.base = base self.altura = altura
def calcular_area(self): return self.base * self.altura
def mostrar_info(self): area = self.calcular_area() # Usar self para llamar método print(f"Área: {area}")
rect = Rectangulo(5, 3)rect.mostrar_info() # Área: 15Ejemplo: Encapsulamiento
Section titled “Ejemplo: Encapsulamiento”class CuentaBancaria: def __init__(self, titular, saldo_inicial): self.titular = titular self.__saldo = saldo_inicial # Privado
def depositar(self, cantidad): if cantidad > 0: self.__saldo += cantidad
def obtener_saldo(self): return self.__saldo
cuenta = CuentaBancaria("Ana", 1000)cuenta.depositar(500)print(cuenta.obtener_saldo()) # 1500👨👩👧 11.6 Herencia y clases hijas
Section titled “👨👩👧 11.6 Herencia y clases hijas”Concepto de herencia
Section titled “Concepto de herencia”La herencia permite crear nuevas clases basadas en clases existentes, heredando sus atributos y métodos.
Sintaxis:
class ClaseHija(ClasePadre): # Código adicionalsuper()
Section titled “super()”La función super() permite acceder a métodos de la clase padre.
Ejemplo: Herencia básica
Section titled “Ejemplo: Herencia básica”class Animal: def __init__(self, nombre): self.nombre = nombre
def hacer_sonido(self): print("El animal hace un sonido")
class Perro(Animal): def hacer_sonido(self): print(f"{self.nombre} dice: ¡Guau!")
class Gato(Animal): def hacer_sonido(self): print(f"{self.nombre} dice: ¡Miau!")
perro = Perro("Max")gato = Gato("Luna")perro.hacer_sonido() # Max dice: ¡Guau!gato.hacer_sonido() # Luna dice: ¡Miau!Ejemplo: Usar super()
Section titled “Ejemplo: Usar super()”class Vehiculo: def __init__(self, marca, modelo): self.marca = marca self.modelo = modelo
class Coche(Vehiculo): def __init__(self, marca, modelo, puertas): super().__init__(marca, modelo) self.puertas = puertas
coche = Coche("Toyota", "Corolla", 4)print(f"{coche.marca} {coche.modelo} - {coche.puertas} puertas")⚙️ 11.7 Métodos especiales: str(), len(), etc.
Section titled “⚙️ 11.7 Métodos especiales: str(), len(), etc.”Métodos mágicos
Section titled “Métodos mágicos”Los métodos especiales permiten personalizar el comportamiento de los objetos.
| Método | Uso | Descripción |
|---|---|---|
__str__() | print(obj) | Representación legible |
__len__() | len(obj) | Longitud del objeto |
__eq__() | obj1 == obj2 | Comparación de igualdad |
__add__() | obj1 + obj2 | Suma de objetos |
Ejemplo: str()
Section titled “Ejemplo: str()”class Libro: def __init__(self, titulo, autor): self.titulo = titulo self.autor = autor
def __str__(self): return f'"{self.titulo}" por {self.autor}'
libro = Libro("Python 101", "Ana García")print(libro) # "Python 101" por Ana GarcíaEjemplo: len()
Section titled “Ejemplo: len()”class Playlist: def __init__(self, nombre): self.nombre = nombre self.canciones = []
def agregar(self, cancion): self.canciones.append(cancion)
def __len__(self): return len(self.canciones)
playlist = Playlist("Favoritas")playlist.agregar("Canción 1")playlist.agregar("Canción 2")print(len(playlist)) # 2📐 11.8 Buenas prácticas al diseñar clases
Section titled “📐 11.8 Buenas prácticas al diseñar clases”Principios de diseño
Section titled “Principios de diseño”| Principio | Descripción |
|---|---|
| Responsabilidad única | Una clase debe tener un solo propósito |
| Encapsulamiento | Ocultar detalles de implementación |
| Nombres descriptivos | Clases y métodos con nombres claros |
| Documentación | Usar docstrings para explicar el código |
Ejemplo: Clase bien diseñada
Section titled “Ejemplo: Clase bien diseñada”class CuentaBancaria: """Representa una cuenta bancaria con operaciones básicas."""
def __init__(self, titular, saldo_inicial=0): """Inicializa una nueva cuenta bancaria.""" self.titular = titular self.__saldo = saldo_inicial
def depositar(self, cantidad): """Deposita dinero en la cuenta.""" if cantidad > 0: self.__saldo += cantidad return True return False
def retirar(self, cantidad): """Retira dinero de la cuenta.""" if 0 < cantidad <= self.__saldo: self.__saldo -= cantidad return True return False
def obtener_saldo(self): """Retorna el saldo actual.""" return self.__saldo
def __str__(self): return f"Cuenta de {self.titular}: {self.__saldo:.2f} USD"
cuenta = CuentaBancaria("Ana García", 1000)cuenta.depositar(500)print(cuenta) # Cuenta de Ana García: 1500.00 USD