30. Programación orientada a objetos VII
Vídeo
Notas personales
Continuemos con el ejemplo de la lección anterior:
# Clase Padre
class Vehiculo():
def __init__(self, marca, modelo):
self.marca = marca
self.modelo = modelo
self.enmarcha = False
self.acelera = False
self.frena = False
def arrancar(self):
self.enmarcha = True
def acelerar(self):
self.acelera = True
def frenar(self):
self.frena = True
def estado(self):
print("Marca:", self.marca, "\nModelo:", self.modelo, "\nEn marcha:",
self.enmarcha, "\nAcelerando:", self.acelera, "\nFrenando:",
self.frena)
# Clase hija
class Moto(Vehiculo):
pass
Construyamos la clase Moto
, añadiendo un comportamiento nuevo, caballito
, que se va a sumar a los cuatro heredados de la clase Vehiculo
:
class Moto(Vehiculo):
hcaballito = ""
def caballito(self):
hcaballito = "Voy haciendo el caballito."
Ahora podríamos teclear:
mi_moto = Moto("Honda", "CBR")
mi_moto.caballito()
mi_moto.estado()
Marca: Honda
Modelo: CBR
En marcha: False
Acelerando: False
Frenando: False
El programa ‘‘funciona’’ (al menos no arroja errores), pero no nos está informando si estamos haciendo el caballito o no.
Abordemos esta situación sobreescribiendo el método estado
heredado de la clase Vehiculo
, para así incorporar la información sobre el nuevo comportamiento de la clase Moto
.
Para sobreescribir un método de la clase padre definimos uno en la clase hija que se caracterice por tener el mismo nombre y número de parámetros:
class Moto(Vehiculo):
hcaballito = ""
def caballito(self):
self.hcaballito = "Voy haciendo el caballito."
def estado(self):
print("Marca:", self.marca, "\nModelo:", self.modelo, "\nEn marcha:",
self.enmarcha, "\nAcelerando:", self.acelera, "\nFrenando:",
self.frena, "\n", self.hcaballito)
De esta manera, la ejecución del siguiente bloque de código:
mi_moto = Moto("Honda", "CBR")
mi_moto.caballito()
mi_moto.estado()
Produce como resultado ahora:
Marca: Honda
Modelo: CBR
En marcha: False
Acelerando: False
Frenando: False
Voy haciendo el caballito.
Modifiquemos el código para albergar la posibilidad de trabajar con furgonetas:
class Furgoneta(Vehiculo):
def carga(self, cargar):
self.cargado = cargar
if self.cargado:
return "La furgoneta está cargada."
else:
return "La furgoneta no está cargada."
Así,
mi_furgo = Furgoneta("Renault", "Kangoo")
mi_furgo.arrancar()
mi_furgo.estado()
mi_furgo.carga(True)
Marca: Renault
Modelo: Kangoo
En marcha: True
Acelerando: False
Frenando: False
Todo funciona de manera adecuada, con la salvedad de que no estamos viendo que la furgoneta está cargada. Como el método carga()
devuelve una cadena de texto, añadiendo una función print()
solucionamos el entuerto:
mi_furgo = Furgoneta("Renault", "Kangoo")
mi_furgo.arrancar()
mi_furgo.estado()
print(mi_furgo.carga(True))
Marca: Renault
Modelo: Kangoo
En marcha: True
Acelerando: False
Frenando: False
La furgoneta está cargada.
Obviamente, una instrucción del tipo mi_moto.carga()
arroja un error, ya que no hereda de Furgoneta
la clase Moto
, sino de Vehiculo
.
Añademos soporte para vehículos electrónicos:
class VehiculoElec():
def __init__(self):
self.autonomia = 100
def cargar_energia(self):
self.cargando = True
Y, a continuación, generemos una clase para trabajar con biciletas eléctricas. Estas tienen marca, modelo, pueden arrancar, frenar… y a la vez también poseen autonomia y la posibilidad de cargar energía. Python nos permite heredar de dos o más clases, que se conoce como herencia múltiple:
class BicicletaElec(VehiculoElec, Vehiculo):
pass
Hemos de tener en cuenta que cuando se da herencia múltiple, a la hora de tomar el constructor o los diferentes métodos, se da la preferencia según hayamos ordenado las clases padres de las que hereda. En este caso, no podemos iniciar una bicicleta eléctrica con marca y modelo, aprovechando así el constructor de la clase Vehiculo
, ya que la clase VehiculoElec
posee su propio constructor y este último tiene preferencia por haber colocado esta clase primero en la definición de BicicletaElec
.
mi_bici = BicicletaElec("Orbea", "HCI30")
Traceback (most recent call last):
File "prac30_poo7_3.py", line 58, in <module>
mi_bici = BicicletaElec("Orbea", "HCI30")
TypeError: __init__() takes 1 positional argument but 3 were given
No obstante, si intercambiamos el orden de las clases padre en la definición de BicicletaElec
:
class BicicletaElec(Vehiculo, VehiculoElec):
pass
mi_bici = BicicletaElec("Orbea", "HCI30")
mi_bici.estado()
La ejecución ya no arroja errores, mostrando el siguiente resultado:
Marca: Orbea
Modelo: HCI30
En marcha: False
Acelerando: False
Frenando: False
Código fuente
El código fuente y los posibles ficheros externos generados correspondientes a esta lección se encuentran disponibles para su consulta en la carpeta /lecciones/30/
del
repositorio.