Programación Orientada a Objetos (POO): Abstracción, Encapsulamiento, Herencia, Polimorfismo
Programación Orientada a Objetos (POO) - Explicación para Principiantes
La POO es una forma de organizar código como si fueran objetos del mundo real. Imagina que programas con "cosas" que tienen características y comportamientos.
📦 Los 4 Pilares Fundamentales
1. 🔍 Abstracción - Simplificar la realidad
Imagina: Cuando usas un televisor, solo necesitas saber usar el control remoto, no cómo funciona internamente.
En código: Mostramos solo lo esencial y ocultamos los detalles complicados.
# Ejemplo: Un auto abstracto
class Auto:
def encender(self):
# No necesitas saber cómo funciona el motor
pass
def acelerar(self):
# Solo sabes que al presionar el pedal, el auto acelera
pass2. 🔒 Encapsulamiento - Proteger la información
Imagina: Tu cuerpo: puedes controlar tus brazos, pero no puedes acceder directamente a tu corazón.
En código: Protegemos los datos internos y controlamos cómo se accede a ellos.
class CuentaBancaria:
def __init__(self):
self.__saldo = 0 # __ significa "privado"
# Métodos públicos para interactuar
def depositar(self, cantidad):
if cantidad > 0:
self.__saldo += cantidad
def get_saldo(self): # Controlamos cómo se accede al saldo
return self.__saldo3. 👨👧👦 Herencia - Reutilizar y extender
Imagina: Heredas características de tus padres, pero también tienes tus propias cualidades.
En código: Una clase puede heredar de otra y agregar nuevas funcionalidades.
# Clase padre
class Animal:
def respirar(self):
return "Estoy respirando"
# Clase hija que hereda de Animal
class Perro(Animal): # Herencia: Perro ES UN Animal
def ladrar(self):
return "¡Guau guau!"
# Uso
mi_perro = Perro()
print(mi_perro.respirar()) # Heredado de Animal
print(mi_perro.ladrar()) # Propio de Perro4. 🎭 Polimorfismo - Múltiples formas
Imagina: El botón "encender" funciona diferente en un TV, un auto y un teléfono, pero todos tienen ese botón.
En código: Diferentes objetos pueden responder al mismo mensaje de forma particular.
class Gato(Animal):
def hacer_sonido(self):
return "Miau"
class Pajaro(Animal):
def hacer_sonido(self):
return "Pío pío"
# Polimorfismo en acción
animales = [Gato(), Pajaro()]
for animal in animales:
print(animal.hacer_sonido()) # Mismo método, diferentes resultados
# Output: Miau
# Pío pío🏗️ Analogía Final: Construyendo una Casa
Abstracción: Sabes que una casa tiene puertas y ventanas, pero no necesitas conocer los detalles de construcción.
Encapsulamiento: La instalación eléctrica está dentro de las paredes, protegida.
Herencia: Un apartamento ES UNA casa, pero con características adicionales (portero, ascensor).
Polimorfismo: La puerta de entrada y la del baño se abren de forma diferente, pero ambas son "puertas".
💡 Beneficios de la POO
Código más organizado y fácil de entender
Reutilización de código
Mantenimiento más sencillo
Flexibilidad para hacer cambios
Tutorial POO: ¡Aprende los 4 Pilares de Forma Sencilla!
🤔 ¿Qué es la Programación Orientada a Objetos?
Imagina que en vez de escribir código complicado, creas "objetos" como en la vida real. ¡Es como construir con LEGO!
POO = Organizar código en "objetos" que tienen:
Atributos: Sus características (como el color de un coche)
Métodos: Sus acciones (como acelerar o frenar)
🏗️ Conceptos Básicos
Clase vs Objeto
# La CLASE es el molde (la plantilla)
class Taza:
def __init__(self): # ← Constructor
self.volumen = 250 # Atributos
self.liquido = "café"
self.cantidad = 0
def llenar(self): # Métodos
self.cantidad = self.volumen
def beber(self):
self.cantidad -= 50
# El OBJETO es la taza real que creamos
mi_taza = Taza() # ← Instanciar (crear objeto)
mi_taza.llenar() # ← Usar métodos con "."🎯 Los 4 Pilares de POO
1. 🔍 ABSTRACCIÓN - Elegir lo importante
¿Qué es? Seleccionar solo lo necesario para tu objetivo.
Ejemplo: Una Canción
# Para una biblioteca musical:
class CancionBiblioteca:
def __init__(self, nombre, artista, duracion, genero):
self.nombre = nombre # ← Solo estos atributos
self.artista = artista # son importantes
self.duracion = duracion
self.genero = genero
def escuchar(self):
print("Reproduciendo...")
# Para una tienda online:
class CancionTienda:
def __init__(self, nombre, artista, precio):
self.nombre = nombre # ← Diferentes atributos
self.artista = artista # para diferente objetivo
self.precio = precio
def comprar(self):
print("Comprada!")¡Tú decides qué es importante!
2. 🔒 ENCAPSULACIÓN - Proteger tus datos
Problema: Cualquiera puede modificar tus atributos directamente.
Solución: Hacer atributos privados y controlar el acceso.
class Personaje:
def __init__(self, nombre, vida):
self.nombre = nombre
self.__vida = vida # ← Privado (con __)
self.__contador = 3 # ← Nadie puede tocarlo directamente
# Métodos públicos para interactuar
def turno(self, accion):
if self.__contador > 0:
if accion == "atacar":
self.__atacar() # ← Método privado
elif accion == "mover":
self.__mover()
self.__contador -= 1
# Métodos privados (solo usados internamente)
def __atacar(self):
print("¡Ataque!")
def __mover(self):
print("Movimiento")
# Getters y Setters (controlados)
def get_contador(self):
return self.__contador
def set_contador(self, valor):
if valor >= 0: # ← Controlamos que no sea negativo
self.__contador = valor
else:
print("¡Error! No puede ser negativo")
# Uso CORRECTO:
heroe = Personaje("Guerrero", 100)
heroe.turno("atacar") # ✅ Bien: usando turno
print(heroe.get_contador()) # ✅ Bien: usando getter
heroe.set_contador(5) # ✅ Bien: usando setter
# heroe.__vida = -50 # ❌ Error: atributo privado
# heroe.__atacar() # ❌ Error: método privado3. 👨👧👦 HERENCIA - No repitas código
¿Qué es? Crear nuevas clases basadas en clases existentes.
# Clase PADRE (superclase)
class Personaje:
def __init__(self, nombre, fuerza, inteligencia, defensa):
self.nombre = nombre
self.fuerza = fuerza
self.inteligencia = inteligencia
self.defensa = defensa
self.vida = 100
def atacar(self):
return self.fuerza * 1.5
def mover(self):
print(f"{self.nombre} se mueve")
# Clases HIJAS (subclases) que HEREDAN todo
class Guerrero(Personaje): # ← Guerrero ES UN Personaje
def __init__(self, nombre, fuerza, inteligencia, defensa, espada):
super().__init__(nombre, fuerza, inteligencia, defensa)
self.espada = espada # ← Atributo nuevo
def golpe_especial(self): # ← Método nuevo
return self.fuerza * 3
class Mago(Personaje): # ← Mago ES UN Personaje
def __init__(self, nombre, fuerza, inteligencia, defensa, varita):
super().__init__(nombre, fuerza, inteligencia, defensa)
self.varita = varita # ← Atributo nuevo
def lanzar_hechizo(self): # ← Método nuevo
return self.inteligencia * 2
# Uso:
guerrero = Guerrero("Conan", 90, 30, 80, "Espadón")
mago = Mago("Merlín", 30, 95, 40, "Varita de roble")
print(guerrero.atacar()) # ✅ Heredado de Personaje
print(mago.atacar()) # ✅ Heredado de Personaje
print(guerrero.golpe_especial()) # ✅ Solo de Guerrero4. 🎭 POLIMORFISMO - Mismo método, diferentes comportamientos
¿Qué es? Un método puede actuar diferente según qué clase lo use.
# Redefinimos el método atacar en las clases hijas
class Guerrero(Personaje):
def atacar(self):
return self.fuerza * 2 + 10 # ← Diferente cálculo
class Mago(Personaje):
def atacar(self):
return self.inteligencia * 3 # ← Diferente cálculo
# ¡Magia del polimorfismo!
def calcular_daño(personaje): # ← Acepta CUALQUIER Personaje
return personaje.atacar() # ← Cada uno usa SU versión de atacar
# Probamos:
guerrero = Guerrero("Conan", 90, 30, 80)
mago = Mago("Merlín", 30, 95, 40)
print(calcular_daño(guerrero)) # → 190 (90*2 + 10)
print(calcular_daño(mago)) # → 285 (95*3)
# ¡El mismo código funciona para diferentes objetos!🎮 Ejemplo Completo: Sistema de Juego
class Personaje:
def __init__(self, nombre):
self.nombre = nombre
self.__vida = 100
self.__contador_acciones = 3
def turno(self, accion):
if self.__contador_acciones > 0:
if accion == "atacar":
daño = self.atacar()
print(f"{self.nombre} causa {daño} de daño")
elif accion == "mover":
self.mover()
self.__contador_acciones -= 1
else:
print("¡Sin acciones disponibles!")
def atacar(self):
return 10 # Daño base
def mover(self):
print(f"{self.nombre} se mueve")
class Guerrero(Personaje):
def atacar(self): # ← Polimorfismo
return 25 # Los guerreros hacen más daño
class Mago(Personaje):
def atacar(self): # ← Polimorfismo
return 15 # Los magos hacen daño mágico
def lanzar_hechizo(self):
return 30
# ¡Juguemos!
personajes = [Guerrero("Thor"), Mago("Gandalf")]
for personaje in personajes:
personaje.turno("atacar") # ← Cada uno usa SU ataque✅ Resumen Final
| Pilar | ¿Qué hace? | Ejemplo de la vida real |
|---|---|---|
| Abstracción | Elegir lo importante | Un coche: color, modelo, pero no cada tornillo |
| Encapsulación | Proteger datos | Tu cuerpo: no puedes controlar directamente tu corazón |
| Herencia | Reutilizar código | Un Ferrari ES UN coche, con extras |
| Polimorfismo | Mismo método, diferentes resultados | Botón "encender" funciona diferente en TV, auto, teléfono |
🚀 ¿Por qué usar POO?
✅ Código más organizado y fácil de entender
✅ Reutilización - No repitas código
✅ Mantenimiento más sencillo
✅ Flexibilidad para hacer cambios
¡Ahora sí entiendes POO! 🎉 En el próximo tutorial veremos cómo aplicar esto en Python con código real.
Comentarios
Publicar un comentario