Programación Orientada a Objetos: Implementación de Clases y Herencia
Resumen
Construir un sistema de concesionaria en Python permite entender cómo la herencia y el polimorfismo trabajan juntos para crear código reutilizable y organizado. A partir de una superclase Vehiculo, se extienden clases hija como Bicicleta, Auto y Camion, cada una con comportamientos propios, mientras que las clases Comprador y Concesionaria orquestan la lógica de negocio interactuando únicamente con la clase padre.
¿Cómo se crean las clases hija bicicleta y camión?
La clase Bicicleta hereda de Vehiculo y reutiliza todos los parámetros definidos en la superclase [01:08]. Sin embargo, sus métodos reflejan un comportamiento diferente: al no tener motor, los mensajes cambian a "la bicicleta está en marcha" y "la bicicleta se ha detenido", en lugar de hacer referencia a un motor.
Este es un ejemplo claro de sobrescritura de métodos (method overriding): la clase hija redefine funciones heredadas para adaptar su comportamiento sin modificar la clase padre.
python
class Bicicleta(Vehiculo):
def iniciar(self):
print("La bicicleta está en marcha")
def detener(self):print("La bicicleta se ha detenido")
Por otro lado, la clase Camion también hereda de Vehiculo, pero conserva la referencia al motor [02:25], ya que tanto el auto como el camión comparten esa característica.
python
class Camion(Vehiculo):
def iniciar(self):
print("El motor del camión está en marcha")
def detener(self):print("El motor del camión se ha detenido")
Aquí se evidencia el polimorfismo: el mismo método (iniciar, detener) se comporta de forma distinta según la clase que lo implemente.
¿Qué hace la clase comprador y cómo interactúa con los vehículos?
La clase Comprador no hereda de ninguna otra clase [03:15]. Su constructor recibe únicamente un nombre y crea una lista vacía donde se almacenarán los vehículos adquiridos.
python
class Comprador:
def init(self, nombre):
self.name = nombre
self.autos = []
¿Cómo funciona el método comprar vehículo?
El método comprar_vehiculo recibe un objeto de tipo Vehiculo [03:50]. Antes de concretar la compra, consulta si el vehículo está disponible mediante un método del propio objeto. Si lo está, ejecuta vender() sobre el vehículo y lo añade a la colección del comprador. En caso contrario, muestra un mensaje indicando que la marca no está disponible [05:00].
Se verifica disponibilidad con vehiculo.esta_disponible().
Se ejecuta vehiculo.vender() para cambiar el estado.
Se agrega el objeto a la lista self.autos.
¿Cómo se consulta la disponibilidad?
Otro método permite consultar el estado de un vehículo [05:30]. Si está disponible, la variable de estado se establece como "disponible"; si no, como "no disponible". Luego se imprime la marca, el estado y el precio usando get_price() [06:30].
Este diseño demuestra la encapsulación: el comprador no accede directamente a los atributos internos del vehículo, sino que utiliza métodos públicos para interactuar con él.
¿Cómo se estructura la clase concesionaria?
La clase Concesionaria (dealership) maneja dos colecciones principales [07:05]:
El método para añadir vehículos recibe un objeto de tipo Vehiculo, lo agrega al inventario y confirma con un mensaje que incluye la marca [07:50]. De forma similar, el método para registrar clientes recibe un objeto Comprador y lo añade a la lista de customers [08:30].
Por último, el método mostrar_disponibles recorre el inventario con un for y filtra únicamente los vehículos cuyo método esta_disponible() devuelva verdadero [09:20]. Para cada uno imprime la marca y el precio.
python
def mostrar_disponibles(self):
print("Vehículos disponibles en la tienda:")
for vehiculo in self.inventario:
if vehiculo.esta_disponible():
print(f"{vehiculo.marca} - {vehiculo.get_price()}")
Lo más importante de este diseño es que la concesionaria no interactúa directamente con las clases hija (Auto, Bicicleta, Camion), sino con los parámetros y métodos establecidos en la clase padre Vehiculo [03:00]. Esto es la abstracción en acción: se trabaja con una interfaz común sin preocuparse por la implementación específica de cada tipo de vehículo.
Con todas las clases definidas, el siguiente paso natural es crear las instancias y poner en práctica los cuatro fundamentos de la programación orientada a objetos: herencia, polimorfismo, encapsulación y abstracción [10:20]. ¿Qué tipo de vehículo agregarías primero al inventario?
Carli podrías por favorsito aclarar cuando usas algún elemento del código como buena practica, cosas como el uso del return, y get para llamar variables o consultar en lugar de llamar a los parámetros directamente, estas buenas practicas que escribes en automático me generan confusión y retrasan el proceso de aprendizaje en consultas a gtp. Me gustaría poder enfocar mas el tiempo en pensar en flujos y no en sintaxis :C. seria genial si nos dejas mensajitos aclaratorios :D
Te apoyo!
Concuerdo contigo, hay cosas que se están pasando por alto y no son explicadas, y esto de cierta manera frustran, ya que hace creer que no se tiene las bases suficientes aún, pero esas mismas cosas no son básicas y necesariamente requieren de una explicación a fondo
En la clase pasada tuvo un error de identación que no aclaró en esta sesión ya que creó la clase car dentro de la clase vehicle y en esta nueva clase ya aparece corregido. Si depronto alguien se atasca con eso, sólo es correr esa clase un tab hacia atrás.
Muchas gracias
Solo oor esto vine a los comentarios muchas gracias, lo vi raro cuando lo hizo dentro de la clase Vehicle pero como no aclaro pense el error era mio. Gracias de nuevo
El curso venía bien estructurado y me estaba gustando, desde que entramos a POO sinceramente todo se desorganizó, no explica bien los conceptos, ni por qué los hace, se supone que es un curso para principiantes y me frustro mucho cuando no entiendo ni el por qué realizan ciertas cosas, no me explican la estructura ni la lógica.
Hola, a esta altura ya debes de entenderlo y haberlo solucionado.
Claramente no está para nada mal buscar en otras fuentes los fundamentos o explicaciones de cada una de las cosas que no entendemos, pero desde la experiencia te digo, lo que mas me ha ayudado a comprender todo en programación es no parar nunca de programar, de escribir todos los días, aunque sean 2 funciones.
no entendi si estamos e un concesionario que tiene que ver que este en marcha, hace confuso el ejemplo
pensé lo mismo
Duda: ¿Por qué declaramos los métodos utilizados en las subclases también en la subclase, me refiero a los métodos stop_engine y start_engine?
Hola! es solo para simular el funcionamiento del vehículo, al iniciar con POO tenemos límite en el uso de herramientas ya que son temas que no hemos visto de momento, por lo que estos métodos solo sirven como ejemplo para emular el funcionamiento de abstracción del mundo real.
Para cambiar su comportamiento.
Como cada vehículo requiere un print distinto, entonces se define esa función para cada vehículo particular.
Apunte sobre la Herencia en el Código 😊
¿Qué es la Herencia?
La herencia es como una receta familiar 👨🍳. La clase padre (Vehiculo) tiene los ingredientes básicos 🧂 y las instrucciones generales 📝. Las subclases (Car y Motorcycle) heredan esos elementos, pero también pueden agregar sus propios toques especiales ✨ ¡y hasta crear nuevas recetas a partir de la original!
¿Cómo funciona en este código?
Clase PadreVehiculo:
Define los ingredientes básicos 🧂 (atributos) como marca, modelo, color, precio, esta_disponible.
Incluye instrucciones generales 📝 (métodos) como vender, disponibilidad, get_precio.
Tiene instrucciones "pendientes" 🚧 (NotImplementedError en start_engine y stop_engine) que las subclases deben completar.
SubclasesCaryMotorcycle:
Heredan la receta base de Vehiculo 📖
Usan super().__init__(...) para preparar los ingredientes básicos heredados 🧂
Añaden sus propios ingredientes especiales ✨ (num_puertas para Car y cilindrada para Motorcycle)
Completan las instrucciones pendientes 🚧, cada una a su manera (start_engine y stop_engine)
Tienen sus propias instrucciones exclusivas 🤫 (get_num_puertas para Car y get_cilindrada para Motorcycle)
Palabras Clave especiales:
NotImplementedError 🚧: Es como un recordatorio 📝 para las subclases: "¡Oye, no olvides completar esta instrucción!"
return : Es como devolver un regalo 🎁 al final de una función. ¡Útil para obtener información de un objeto!
get_algo 🔍: Es una forma educada de pedirle a un objeto que te muestre algo específico. ¡Como preguntar "¿Cuál es tu número de puertas?" a un auto! 🚗
# Va ser la clase padreclassVehiculo:def__init__(self, marca, modelo, color, precio):"""
Constructor de la clase Vehiculo. Inicializa un nuevo vehículo con los atributos proporcionados.
""" self.marca = marca
self.modelo = modelo
self.color = color
self.precio = precio
self.esta_disponible =True# Indica si el vehículo está disponible para la ventadefvender(self):"""
Marca el vehículo como vendido si está disponible.
"""if self.esta_disponible: self.esta_disponible =Falseprint(f"El vehículo {self.marca}{self.modelo} ha sido vendido")else:print(f"El vehículo {self.marca}{self.modelo} no está disponible")defdisponibilidad(self):"""
Devuelve True si el vehículo está disponible, False de lo contrario
"""return self.esta_disponible
defget_precio(self):"""
Devuelve el precio del vehículo
"""return self.precio
defstart_engine(self):"""
Método abstracto para encender el motor. Debe ser implementado por las subclases
"""raise NotImplementedError("Subclases deben implementar este método")defstop_engine(self):"""
Método abstracto para apagar el motor. Debe ser implementado por las subclases
"""raise NotImplementedError("Subclases deben implementar este método")"""
Subclase: Auto
"""classCar(Vehiculo):def__init__(self, marca, modelo, color, precio, num_puertas):"""
Constructor de la clase Car. Hereda de la clase Vehiculo y agrega el atributo num_puertas
"""super().__init__(marca, modelo, color, precio)# Llama al constructor de la clase padre self.num_puertas = num_puertas
defstart_engine(self):"""
Implementación específica para encender el motor de un auto
"""print(f"El auto {self.marca}{self.modelo} está en funcionamiento")defstop_engine(self):"""
Implementación específica para apagar el motor de un auto
"""print(f"El auto {self.marca}{self.modelo} se detuvo")defget_num_puertas(self):"""
Devuelve el número de puertas del auto
"""return self.num_puertas
"""
Subclase: Motocicleta
"""classMotorcycle(Vehiculo):def__init__(self, marca, modelo, color, precio, cilindrada):"""
Constructor de la clase Motorcycle. Hereda de la clase Vehiculo y agrega el atributo cilindrada
"""super().__init__(marca, modelo, color, precio) self.cilindrada = cilindrada
defstart_engine(self):"""
Implementación específica para encender el motor de una motocicleta
"""print(f"La motocicleta {self.marca}{self.modelo} está en funcionamiento")defstop_engine(self):"""
Implementación específica para apagar el motor de una motocicleta
"""print(f"La motocicleta {self.marca}{self.modelo} se detuvo")defget_cilindrada(self):"""
Devuelve la cilindrada de la motocicleta
"""return self.cilindrada
# Creacion de objetos car1 = Car("Toyota","Camry","Rojo",25000,4)car2 = Car("Honda","Civic","Azul",22000,4)car3 = Car("Ford","Mustang","Negro",35000,2)motorcycle1 = Motorcycle("Honda","CBR","Negro",30000,500)motorcycle2 = Motorcycle("Honda","CBR","Verde",25000,500)# Utilizar metodos car1.start_engine()car1.stop_engine()car1.vender()motorcycle1.start_engine()motorcycle1.stop_engine()motorcycle1.vender()car1.vender()# Intentar vender de nuevo, pero no estará disponiblecar2.esta_disponible =False# Cambiar la disponibilidad manualmentecar2.vender()motorcycle2.cilindrada =600# Modificar la cilindradaprint(motorcycle2.cilindrada)# Imprimir la nueva cilindrada```# Va ser la clase padre
Reutilización de Código: ¡No hace falta repetir la receta base una y otra vez! ♻️
<!---->
Organización: ¡Todo está en su lugar, como una cocina bien ordenada! 🗄️
Flexibilidad: ¡Cada subclase puede tener su propio estilo! 🎨
Polimorfismo: ¡Puedes tratar a todos los vehículos por igual, aunque sean diferentes! 🚗🏍️ ¡Es como si todos hablaran el mismo idioma! 🗣️
Ejemplo de Polimorfismo:
Pythonvehiculos = [car1, motorcycle1]
for vehiculo in vehiculos:
vehiculo.start_engine() 🏁 # ¡Cada vehículo se enciende a su manera!
Desde que comenzamos con el tema de POO he tenido dificultades ya que me surgen muchas dudas durante los videos , al principio creí que solo era yo , pero al revisar los comentarios me doy cuenta que varios de mis compañeros tiene problemas similares.
Platzi tiene un problema muy grande y es que los cursos van estructurados para principiantes pero de un momento a otro pasan a ser para seniors, en este caso desde que entramos a POO todo se desorganizó, no explican bien los conceptos, ni por qué los hace y termina uno pasando a otras plataformas a buscar el conocimiento que se supone que están enseñando en el curso para principiantes.
La verdad, creo que este curso no es solo para principiantes, quizá por eso no se llama curso de fundamentos..., si necesitas tener dominio sobre algún lenguaje. A mí personalmente se me ha facilitado entender porque ya llevo tiempo trabajando con JS, entonces comparas conceptos entre lenguajes y entiendes mejor. Puedes pedirle a chat gpt que te explique algún concepto que no te quede tan claro e incluso pedir que te lea la respuesta y tu la escuchas, será más fácil de digerir así.
Si quieres agregar nuevos atributos a las clases hijas, puedes usar la función reservada "super()" así:
#EjerciciosclassVehicle:def__init__(self,brand,model,price): self.brand = brand
self.model = model
self.price = price
self.is_available =Truedefsell(self):if self.is_available: self.is_available =Falseprint(f"El vehiculo {self.brand}. Ha sido vendido.")else:print(f"El vehiculo {self.brand}. No está vendido.")defcheck_available(self):return self.is_available
defget_price(self):return self.price
defstart_engine(self):raise NotImplementedError("Este método debe ser implementado por la subclase")defstop_engine(self):raise NotImplementedError("Este método debe ser implementado por la subclase")classCar(Vehicle):defstart_engine(self):ifnot self.is_available:returnf"El motor del coche {self.brand} está en marcha."else:returnf"El coche {self.brand} no está disponible."defstop_engine(self):ifnot self.is_available:returnf"El motor del coche {self.brand} se ha detenido."else:returnf"El coche {self.brand} no está disponible."classBike(Vehicle):defstart_engine(self):ifnot self.is_available:returnf"La bicicleta {self.brand} está en marcha."else:returnf"La bicicleta {self.brand} no está disponible."defstop_engine(self):ifnot self.is_available:returnf"La bicicleta {self.brand} se ha detenido."else:returnf"La bicicleta {self.brand} no está disponible."classTruck(Vehicle):defstart_engine(self):ifnot self.is_available:returnf"El motor del camión {self.brand} está en marcha."else:returnf"El camión {self.brand} no está disponible."defstop_engine(self):ifnot self.is_available:returnf"El motor del camión {self.brand} se ha detenido."else:returnf"El camión {self.brand} no está disponible."classCustomer:def__init__(self,name): self.name = name
self.purchased_vehicles =[]defbuy_vehicle(self, vehicle: Vehicle):if vehicle.check_available(): vehicle.sell() self.purchased_vehicles.append(vehicle)else:print(f"Lo siento, {vehicle.brand} no está disponible.")definquire_vehicle(self, vehicle: Vehicle):if vehicle.check_available(): availablity ="Disponible"else: availablity ="No disponible"print(f"El {vehicle.brand} está {availablity} y cuesta {vehicle.get_price()}.")classDealership:def__init__(self): self.inventory =[] self.customers =[]defadd_vehicles(self, vehicle: Vehicle): self.inventory.append(vehicle)print(f"El {vehicle.brand} ha sido añadido al inventario.")defregister_customers(self, customer: Customer): self.customers.append(customer)print(f"El cliente {customer.name} ha sido añadido.")defshow_available_vehicle(self):print("Vehiculos disponibles en la tienda")for vehicle in self.inventory:if vehicle.check_available():print(f" - {vehicle.brand} por {vehicle.get_price()}.")
Hola muchachos vengo a dar mi aporte con el curso desde la perspectiva de alguien que ya lleva tiempo programando.
Desde mi punto de vista es verdad que hay cosas que dan por sentadas que ya concen. Precisamente por que este curso deberia tomarse dspues de haber visto los cursos de programación basica. Una vez tienes los conceptos es mas sencillo de entender ciertos ajustes que hace la profesora. Si tienen dudas les recomendaria tomar esos cursos antes o preguntarle a la IA de la clase ! Voy a aclarar ciertos puntos que he visto en los comentarios
Como se resuelve el error de la clase ?: Como se vio en las primeras clases ese error sucede por la sintaxis de python la clase Car esta dentro de la clase vehicle lo cual no puede ser, devolviendo un tab se soluciona para tener la misma indesxación que su clase padre
Que son los metodos start y stop engine: Son metodos que declara la clase padre y deben implementar sus subclases, lo bueno que tiene OOP es que permite tener clases que hereden comportamientos de sus padres. Sin embargo no todas las hijas tendran el mismo comportamiento por lo que podemos definir ciertos metodos que sean implementados por cada una de las hijas. El not implemented error nos permite mandar un error cuando una de nuestras clases hijas no a implementado el metood
Por que implementamos los metodos get? Es una buena practica en POO no acceder a la propiedad directamente. Y generalmente se utilizan metodos para acceder a ellas. Ahora no se ve pero uno puede definir sus metodos como privados, publicos o privados
Espero esto les pueda ayudar un poco !
En video anterior cuando vimos como se declara la clase Bike el codigo nos tiraba un pequeño error justo al declarar:
class Bike(<u>Vehicle</u>):
Se omite como se resuelve y en este video simplemente no está, el error se debe a que la clase Bike se estaba creando dentro de Vehicle y debía estar fuera (Identación)
Gracias, Me devolví a ver todos los videos de POO tratando de resolver este error
Me toca tener optimismo al decir que voy a terminar este curso que fue tan mal desarrollado
Considero valioso que se ejemplifique la herencia en programación orientada a objetos; sin embargo, noto que hay mucho énfasis en la construcción de código y pocos fundamentos conceptuales. Aunque la profesora hace una breve introducción teórica, rápidamente pasa a desarrollar la clase con bastante código, lo que en ocasiones dificulta el seguimiento, especialmente cuando se utilizan atributos en los métodos con nombres similares que pueden generar confusión.
Pienso que el curso sería más completo si se equilibrara lo práctico con una base conceptual más sólida. Es decir, que cada fragmento de código venga acompañado de una explicación clara del porqué y el para qué, de manera que no solo se entienda cómo se escribe, sino también qué significa dentro del contexto de la programación orientada a objetos.
Pienso lo mismo, aunque en lugar de comentar el codigo yo creo que hay conceptos teoricos que deben de dejarlos escritos en un apartado teorico y no solo poner referencias a la documentacion oficial de python.
Yo como principiante no he entendido mucho, siento que tiene mucha dificultad para alguien que está empezando, la verdad al principio parece normal, pero se ha saltado a cosas con mucha complejidad" A mi punto de vista", y muchas veces no explica bien.
Es entendible. Para quienes están comenzando, estaría bien tomar el curso de Programación Básica que ofrece Platzi; incluso creo que es gratuito. Este curso abarca temas fundamentales que te ayudarán a entender mejor algunos conceptos que se ven aquí. Las bases son esenciales para poder comprender y avanzar con confianza.
¿Qué pasa con este curso? Sí, ha venido abarcando temas muy rápido, pero la idea es practicar y dominar cada uno. Haz de cuenta: ella lo explica, tú lo practicas, y luego avanzas al siguiente tema. De eso se trata.
Si hay algo que no entiendes, puedes repetir la clase hasta que te quede claro, o buscar información adicional hasta comprenderlo bien. Lo importante es no quedarse solo con lo que se ve en clase, sino reforzarlo por tu cuenta.
Carli, que es lo que esta pasando, las dos clase anteriores tus códigos no están funcionando y estas creando mas confusion..
Como mejora en este curso me gustaría que las clases tengan ejemplos ya preparados, así nos podemos enfocar en lo relevante.
Mi percepción fue que la mayor parte del tiempo estuvimos viendo cómo se escribían los métodos de clase, en lugar de centrarnos en lo fundamental, que es ver como distintas clases que heredan de una misma clase padre pueden ser tratadas igual.
Hace unas 4 clases que me perdí en el curso, porque aún no entiendo bien, qué debo escribir, Por qué tengo que escribir y para qué debo escribir para hacer código... algún recurso que puedan recomendarme? Gracias
ve el curso "Curso de Fundamentos de Python" con el profe Sergie Code, es muy bueno y entenderás después este curso, ya que me paso lo mismo que a tí
Usa Claude AI:
Es un LLM más eficiente que GPT en lo que al código respecta.
1. Escribe tu propio código, sepas mucho o poco, en VSC.
2. Solicítale Feedback. Pegas tu código en Claude, luego hazle pregunta tras pregunta sobre cómo avanzar hacia lo que te pide la clase:
"Soy beginner en Python, analiza mi código y hazme las correcciones necesarias. Usa un lenguaje apto para principiantes y añade un ejemplo que lo explique mejor."
3. Repite el proceso con el código de la clase. Recuerda que la profa. Carli nos lo deja en los recursos para estudiarlo. Así irás viendo por qué cada código tiene su lugar.
4. Usa recursos de apoyo. Por ejemplo, videos en YT. Incluso blogs online (uno de mis favoritos se llama "El Libro de Python")
5. Practica.
Tómate 30 min o 1 h diarios para escribir código desde tu memoria, sin recurrir a AI, ni a clases ni a recursos. Únicamente hasta el final. Te tienes que forzar a recordar.
Y no olvides que cada quién aprende a su ritmo, lo importante es que nunca pares de aprender.💚
Me arrepiento de haber pagado , mil veces youtube con chat gpt
buenas noches , no se alguien vaya a leer este mensaje en algun momento pero considero que de un momento a otro saltamos de ser principiantes a avanzados y la verdad yo estoy empezando en este mundo de la programación y a partir de la clase 23 se me dificulto enteder los conceptos y me quede con cara de what? cuando dijo lo encender motor y apagar motor
Te recomiendo que leas principios de la programación orientada a objetos (OOP) para entender un poco más lo que esta haciendo la profesora. Lamentablemente no explica, lo otro que te recomiendo es que le digas a ChatGPT "Estoy aprendiendo python, no quiero que me digas donde esta el error. Seras mi profesor y deberás a ayudarme a encontrarlo por medio de decirme cosas que me hagan razonar y conversando juntos haremos que encuentre por mi cuenta el error"
De esta forma chatgpt recibira tu codigo y te ayudara a pensar y le puedes ir preguntando cosas para aprender. Este curso es una buena base, el resto del razonamiento lo tienes que hacer tu con la ventaja de gpt a la mano