31. Programación orientada a objetos VIII
Vídeo
Notas personales
En esta lección estudiaremos el uso de las funciones
super()
eisinstance()
.
Partimos del último ejemplo de la lección anterior:
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)
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."
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)
class VehiculoElec():
def __init__(self):
self.autonomia = 100
def cargar_energia(self):
self.cargando = True
class BicicletaElec(VehiculoElec, Vehiculo):
pass
Si queremos crear un objeto de la clase BicicletaElec
que posea una marca y un modelo, tenemos dos opciones disponibles:
- Acudir al método
__init__()
de la claseVehiculoElec
y copiar las líneas que nos interesen del método homónimo de la claseVehiculo
. No obstante, este enfoque es, cuanto menos, poco elegante. - Utilizar la función
super()
, cuya utilidad reside en que procede a llamar al método de la clase padre.
Veamos esta segunda aproximación con un ejemplo un tanto más sencillo:
class Persona():
def __init__(self, nombre, edad, residencia):
self.nombre = nombre
self.edad = edad
self.residencia = residencia
def describir(self):
print("Nombre:", self.nombre, "\nEdad:", self.edad, "\nResidencia:",
self.residencia)
class Empleado(Persona):
def __init__(self, salario, antiguedad):
self.salario = salario
self.antiguedad = antiguedad
Ahora podríamos comenzar a construir objetos de ambas clases:
antonio = Persona("Antonio", 55, "España")
antonio.describir()
Nombre: Antonio
Edad: 55
Residencia: España
Para constuir un objeto de la clase Empleado
, hemos de tener en cuenta que tomará como argumentos los parámetros declarados en dicha clase, y no los de Persona
. No obstante, a la hora de emplear el método describir()
encontraremos problemas tal y como están programadas ambas clases:
juan = Empleado(1500, 15)
juan.describir()
Traceback (most recent call last):
File "prac31_poo8_2.py", line 24, in <module>
juan.describir()
File "prac31_poo8_2.py", line 8, in describir
print("Nombre:", self.nombre, "\nEdad:", self.edad, "\nResidencia:",
AttributeError: 'Empleado' object has no attribute 'nombre'
Podemos reescribir el constructor de la clase Empleado
, haciendo uso de la función super()
, como sigue:
class Empleado(Persona):
def __init__(self, salario, antiguedad):
super().__init__("Juan", 33, "Italia")
self.salario = salario
self.antiguedad = antiguedad
De manera que ahora el código no arrojará error alguno:
juan = Empleado(1500, 15)
juan.describir()
Nombre: Juan
Edad: 33
Residencia: Italia
No obstante, programado así, todos nuestros empleados se llamarían Juan, tendrían 33 años y serían italianos. Veamos cómo generalizar el funcionamiento de la anterior clase:
class Empleado(Persona):
def __init__(self, salario, antiguedad, nombre_empleado, edad_empleado,
residencia_empleado):
super().__init__(nombre_empleado, edad_empleado, residencia_empleado)
self.salario = salario
self.antiguedad = antiguedad
def describir(self):
super().describir()
print("Salario:", self.salario, "\nAntigüedad:", self.antiguedad)
De paso, hemos mejorado también el método describir()
, que procede a llamar al de la clase padre y, además, añade la información correspondiente al salario y a la antigüedad. De este modo,
juan = Empleado(1500, 15, "Juan", 33, "Italia")
juan.describir()
Nombre: Juan
Edad: 33
Residencia: Italia
Salario: 1500
Antigüedad: 15
La función isinstance()
nos informa si un objeto es instancia de una clase determinada:
juan = Empleado(1500, 15, "Juan", 33, "Italia")
juan.describir()
print(isinstance(juan, Persona)) # True
print(isinstance(juan, Empleado)) # True
marco = Persona("Marco", 51, "Francia")
print(isinstance(marco, Persona)) # True
print(isinstance(marco, Empleado)) # False
Con todo, modifiquemos el ejemplo inicial para permitir que una bicicleta eléctrica admita marca y modelo.
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)
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."
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)
class VehiculoElec(Vehiculo):
def __init__(self, marca, modelo):
super().__init__(marca, modelo)
self.autonomia = 100
def cargar_energia(self):
self.cargando = True
class BicicletaElec(VehiculoElec, Vehiculo):
pass
Notemos que:
- Hemos utilizado la función
super()
en el método__init__()
deVehiculoElec
. - Hemos declarado que la clase
VehiculoElec
hereda deVehiculo
.
Así,
mi_bici = BicicletaElec("Orbea", "HCI30")
mi_bici.estado()
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/31/
del
repositorio.