Curso de introducción a la programación con Python

Autor: Luis Fernando Apáez Álvarez

Clase 7: Introducción a la Herencia

Primeros conceptos

El concepto de Herencia dentro de la POO mantiene la misma idea básica que conocemos del lenguaje común. Por ejemplo, si nos basamos en el árbol genealógico de una persona, podemos decir que el abuelo tiene ciertas características marcadas que heredará a sus hijos, y éstos a su vez a sus hijos; de tal manera el abuelo hereda a sus hijos y a sus nietos ciertas características.

Captura.PNG

Donde claramente la herencia tiene un orden descendente y se basa en niveles jerárquicos (con el abuelo en el primer nivel, su hijo en el segundo nivel y los nietos en el tercer nivel). Lo anterior representa un ejemplo de herencia entre personas, pero podemos llevarlo a un ejemplo de herencia dentro de un lenguaje de programación. Para ello sustituiremos los nombres abuelo, hijo y nietos por clases

Captura1.PNG

representadas también dentro de un sistema jerárquico; siendo así que las clases pueden heredar características (atributos y/o métodos) de otras clases. De lo anterior podemos decir que a la clase 1 se le denomina superclase, a la clase 2 subclase de la clase 1 (simultáneamente, a la clase 2 se le puede denominar superclase de las clase 2 y clase 3); de la misma manera, a la clase 3 y clase 4 las denominamos subclases.

Por otro lado, la herencia dentro de la POO sirve para

Clase Abuelo

Una vez entendidos los primeros conceptos sobre la herencia podemos trabajar el código para crear la superclase Abuelo y la subclase Hijo, intentando trasladar el ejemplo de herencia entre personas a conceptos de programación. Para ello escribimos primero:

Posteriormente creamos la subclase Hijo la cual heredara los atributos y métodos de la clase Abuelo. Debemos aclarar dos puntos

  1. Trivialmente podemos decir que la subclase hijo hereda los métodos hablar() y correr() pues así ocurre en la mayoría de los casos con los hijos.

  2. Podemos decir que la clase hijo hereda algunos de los atributos marcados en el constructor de la clase Abuelo, lo cual si pasa en la herencia entre personas. Por ejemplo, es común que el hijo herede alguna característica del padre, ya sea el color de tez, el color de ojos o de cabello; lo que es claro que el hijo heredará es el apellido paterno. Sin embargo, podemos pensar también que la clase hijo no tendrá el mismo valor en el atributo self.color_ojos, de modo que deberemos realizar las correcciones necesarias para abordar este caso.

Ahora bien, creamos la clase Hijo que por el momento no haga nada

# Creamos la clase Hijo

class Hijo():
    pass

para declarar que la clase Hijo es una subclase de la clase Abuelo, bastará con colocar como parámetro de la clase Hijo el nombre de la superclase en cuestión, esto es

Además, cuando instanciemos esta clase deberemos de pasar también un parámetro (nombre) que exige el constructor de la clase Abuelo pues recordemos que la subclase Hijo hereda los atributos y métodos de la superclase Abuelo. Veamos pues que

Suponiendo que el color de ojos de Pedro es verde en vez de negro, entonces podemos modificar el valor del atributo self.color_ojos como sabemos hacerlo:

el cual sólo se verá afectado en el objeto Pedro y no en los demás objetos. Por ejemplo

Clase Hijo

Hasta ahora ya hemos visto como atributos y métodos son heredados a la subclase Hijo provenientes de la superclase Abuelo; asimismo, observamos que ciertos atributos de la clase Abuelo son distintos en la clase Hijo, donde realizamos (por ejemplo) la modificación pertinente en un objeto en especifico. Posteriormente veremos que la propia clase Hijo puede tener atributos adicionales a los heredados, así como métodos.

Por ende, comenzaremos modificando la clase Hijo agregándole algunos otros atributos y métodos:

# Creamos la clase Hijo como subclase de la clase Abuelo

class Hijo(Abuelo):

    # Constructor
    def __init__(self, num_celular):

        # Atributos
        self.num_celular = num_celular
        self.idiomas = ['Inglés', 'Francés', 'Italianos']
        self.estudiar = False

    # Métodos
    def ir_escuela(self):
        self.estudiar = True
        print('Voy camino a la escuela')

sin embargo el código anterior aún está incompleto. Si bien hemos escrito class Hijo(Abuelo) para hacer referencia a que la clase Hijo es subclase de la clase Abuelo, notemos que la propia clase Hijo tiene un constructor, donde recordemos que esta subclase hereda el constructor de la clase Abuelo, por lo que tenemos un pequeño problema respecto a los parámetros de este constructor. Para arreglar el problema debemos de escribir

    # Constructor:
    # Agregamos el parámetro (o los parámetros) del constructor de la superclase

    def __init__(self, nombre, num_celular):

        # hacemos referencia de los parámetros de la superclase 
        super().__init__(nombre)

        # Atributos
        self.num_celular = num_celular
        self.idiomas = ['Inglés', 'Francés', 'Italianos']
        self.estudiar = False

con lo cual tendremos que

De tal manera, cuando instanciemos la clase Hijo deberemos ingresar dos parámetros: el primero será un valor para el parámetro nombre declarado en el constructor de la superclase abuelo y el segundo será un valor para el parámetro num_celular declarado en el propio constructor de la clase Hijo. Veamos

luego observemos los atributos y métodos propios de la clase Hijo mediante el objeto Zin:

Socialmedia.PNG