Clases y objetos en Python IV

 Sobreescritura de métodos

Al aplicar la herencia de clases en Python suele suceder que un método heredado de una clase superior no se ajuste al 100% de las necesidades de la clase que la hereda, en dicho caso es necesario sobreescribir dicho método usando el mismo nombre declarado en la clase padre a fin de que se sobreescriba el original heredado con el nuevo método definido dentro de la clase hija. Supongamos que definimos una superclase o clase padre llamada vehiculos(), con propiedades tales como marca, modelo, rodando, acelerando y frenando. Ademas posee los métodos encender(), acelerar() y frenar() que modifican los valores de las propiedades rodando, acelerando y frenando.

Ahora supongamos que creamos una clase hija llamada moto(), hija de la clase vehiculos(), por lo tanto la clase moto() hereda todas las propiedades y métodos de la clase padre y a su vez necesita definir algunas propiedades y métodos únicos de una moto, como por ejemplo la propiedad inclina_izquierda e inclina_derecha, con los respectivos métodos que cambian su valor, siendo los métodos inclina_izquierda() e inclina_derecha().

Veamos como queda el código hasta aquí:

import os
os.system('cls')

class vehiculos():
    def __init__(self,marca,modelo) -> None:
        self.marca=marca
        self.modelo=modelo
        self.rodando=False
        self.acelerando=False
        self.frenando=False
   
    def encender(self):
        self.rodando=True

    def acelerar(self):
        self.acelerando=True

    def frenar(self):
        self.frenando=True

    def estado(self):
        print('********** DATOS DEL VEHICULO **********')
        print('Marca: ', self.marca, '\nModelo: ',self.modelo,'\nAcelerando: ',\
            self.acelerando, '\nFrenando: ', self.frenando, '\nRodando: ',\
            self.rodando)

class moto(vehiculos):
    inclina_izquierda = ''
    inclina_derecha = ''
    def inclina_izquierda(self):
        inclina_izquierda = 'Inclinación a la izquierda'
    def incina_derecha(self):
        inclinaderecha = 'Inclinación a la derecha'

moto01=moto('Kawasaki','Ninja')

moto01.estado()

Resultado:

********** DATOS DEL VEHICULO **********

Marca:  Kawasaki

Modelo:  Ninja

Acelerando:  False

Frenando:  False

Rodando:  False

Como podemos comprobar la clase hija moto(), ha heredado las propiedades y métodos de la case padre vehiculo() y al ejecutar el método estado() del objeto instanciado moto01 se han mostrado correctamente los datos de la clase instanciada con la marca Kawasaki y modelo Ninja, pudiendo ver el estado de las propiedades Acelerando, Frenando y Rodando. Sin embargo no es posible ver el estado de las propiedades inclina_derecha o inclina_izquierda, propias de la clase moto, ya que estas no están definidas en el método estado() de la clase padre original vehiculo(). Para solventar esta situación es necesario hacer lo que se conoce como sobreescritura de métodos, que consiste básicamente en redefinir el método heredado de la clase padre dentro de la clase hija. Esto se hace definiendo un método en la clase hija con el mismo nombre que el método de la clase padre. Veamos el código para aclarar mas el tema:


import os
os.system('cls')

class vehiculos():
    def __init__(self,marca,modelo) -> None:
        self.marca=marca
        self.modelo=modelo
        self.rodando=False
        self.acelerando=False
        self.frenando=False
   
    def encender(self):
        self.rodando=True

    def acelerar(self):
        self.acelerando=True

    def frenar(self):
        self.frenando=True

    def estado(self):
        print('********** DATOS DEL VEHICULO **********')
        print('Marca: ', self.marca, '\nModelo: ',self.modelo,'\nAcelerando: ',\
            self.acelerando, '\nFrenando: ', self.frenando, '\nRodando: ',\
            self.rodando)

class moto(vehiculos):
    inclinacion='Neutral'
    def inclinar(self,direccion):
        self.inclinacion=direccion
    def estado(self):
        print('********** DATOS DEL VEHICULO **********')
        print('Marca: ', self.marca, '\nModelo: ',self.modelo,'\nAcelerando: ',\
            self.acelerando, '\nFrenando: ', self.frenando, '\nRodando: ',\
            self.rodando, '\nInclinación: ',self.inclinacion)
   
moto01=moto('Kawasaki','Ninja')
moto01.inclinar('Derecha')
moto01.estado()

Resultado:

********** DATOS DEL VEHICULO **********

Marca:  Kawasaki

Modelo:  Ninja

Acelerando:  False

Frenando:  False

Rodando:  False

Inclinación:  Derecha

Como podemos comprobar Python a sobreescrito el método heredado estado() de la superclase vehiculo() en la clase moto() con el método estado() propio de esta clase, ya que como se puede observar en el método estado() original no se encuentra la referencia a la propiedad inclinación, ya que esta propiedad es exclusiva de las motos y bicicletas (al menos en condiciones normales de uso). También es importante destacar que se ha hecho llamado al método inclinacion(), el cual define el estado de la propiedad inclinación a través del parámetro direccion, indicando así hacia que lado la moto esta inclinandose o si no tiene inclinación alguna (neutral). en resumen de esta manera se sobreescriben los métodos heredados para adaptarlos a la subclase de acuerdo a sus necesidades particulares.

Nótese que el estado por defecto de la propiedad inclinacion definido en la subclase moto es 'Neutral', sin embargo esta propiedad se puede modificar a través del método inclinar(), el cual recibe como parámetro de entrada el lado al que va a inclinar la moto, en el ejemplo ejecutamos el método inclinar('Derecha') para hacer que la propiedad inclinación cambie a 'Derecha'. Si por alguna razón no se ejecuta el método inclinar() el valor que va a tener la propiedad inclinación en la subclase moto es 'Neutral'. Veamos que pasa si comentamos la línea que llama al método inclinar() antes de ejecutar el método estado() de la subclase moto:

import os
os.system('cls')

class vehiculos():
    def __init__(self,marca,modelo) -> None:
        self.marca=marca
        self.modelo=modelo
        self.rodando=False
        self.acelerando=False
        self.frenando=False
   
    def encender(self):
        self.rodando=True

    def acelerar(self):
        self.acelerando=True

    def frenar(self):
        self.frenando=True

    def estado(self):
        print('********** DATOS DEL VEHICULO **********')
        print('Marca: ', self.marca, '\nModelo: ',self.modelo,'\nAcelerando: ',\
            self.acelerando, '\nFrenando: ', self.frenando, '\nRodando: ',\
            self.rodando)

class moto(vehiculos):
    inclinacion='Neutral'
    def inclinar(self,direccion):
        self.inclinacion=direccion
    def estado(self):
        print('********** DATOS DEL VEHICULO **********')
        print('Marca: ', self.marca, '\nModelo: ',self.modelo,'\nAcelerando: ',\
            self.acelerando, '\nFrenando: ', self.frenando, '\nRodando: ',\
            self.rodando, '\nInclinación: ',self.inclinacion)
   
moto01=moto('Kawasaki','Ninja')
#moto01.inclinar('Derecha')
moto01.estado()

Resultado:

********** DATOS DEL VEHICULO **********

Marca:  Kawasaki

Modelo:  Ninja

Acelerando:  False

Frenando:  False

Rodando:  False

Inclinación:  Neutral


Como podemos comprobar el valor de la propiedad inclinacion es la que tiene la subclase moto() por defecto. De esta manera podemos ver como heredar propiedades y métodos de una superclase y adaptarlos a la subclase que los hereda.

Supongamos que deseamos ampiar el programa para incluir una clas de vehiculos tipo camioneta que acepte la propiedad cargado si o no. El código quedaría como sigue:

import os
os.system('cls')

class vehiculos():
    def __init__(self,marca,modelo) -> None:
        self.marca=marca
        self.modelo=modelo
        self.rodando=False
        self.acelerando=False
        self.frenando=False
   
    def encender(self):
        self.rodando=True

    def acelerar(self):
        self.acelerando=True

    def frenar(self):
        self.frenando=True

    def estado(self):
        print('********** DATOS DEL VEHICULO **********')
        print('Marca: ', self.marca, '\nModelo: ',self.modelo,'\nAcelerando: ',\
            self.acelerando, '\nFrenando: ', self.frenando, '\nRodando: ',\
            self.rodando)

class moto(vehiculos):
    inclinacion='Neutral'
    def inclinar(self,direccion):
        self.inclinacion=direccion
    def estado(self):
        print('********** DATOS DEL VEHICULO **********')
        print('Marca: ', self.marca, '\nModelo: ',self.modelo,'\nAcelerando: ',\
            self.acelerando, '\nFrenando: ', self.frenando, '\nRodando: ',\
            self.rodando, '\nInclinación: ',self.inclinacion)

class camioneta(vehiculos):
    cargado=False
    def carga(self,cargar):
        self.cargado=cargar
        if self.cargado:
            return 'Camioneta cargada'
        else:
            return 'Camioneta vacía'
   
    def estado(self):
        print('********** DATOS DEL VEHICULO **********')
        print('Marca: ', self.marca, '\nModelo: ',self.modelo,'\nAcelerando: ',\
            self.acelerando, '\nFrenando: ', self.frenando, '\nRodando: ',\
            self.rodando, '\nCargado: ',self.cargado, '\nEstado de la carga: ',\
            self.carga(self.cargado))

Resultado:

Modelo:  S10

Acelerando:  True

Frenando:  False

Rodando:  False

Cargado:  True

Estado de la carga:  Camioneta cargada

********** DATOS DEL VEHICULO **********

Marca:  Chevrolet

Modelo:  S10

Acelerando:  True

Frenando:  False

Rodando:  False

Cargado:  False

Estado de la carga:  Camioneta vacía


Como podemos comprobar, la clase camioneta ha heredado las propiedades y métodos de su clase padre y adicionalmente tiene la propiedad exclusiva cargado si o no. Ademas posee el método exclusivo cargar() a través del cual recibiendo un argumento booleano establece y devuelve una cadena de texto con el estado de la carga actual. Nota: la redundancia de la impresión del estado de la carga y el llamado al método carga con el estado booleano de la propiedad <cargado> en el método estado() es para fines ilustrativos del uso de los mismos.

Comentarios

Entradas populares