POO | Entendiendo la herencia de clases

pastel herencia programacion

En este artículo desarrollaremos código

Puedes consultar el código de esta practica en el siguiente repositorio de github.

Generalmente cuando pensamos en herencia. Pensamos en aquel terreno del abuelo por el que se pelean nuestros tíos. O en aquella fortuna que por azares del destino recibamos por parte de algún pariente desconocido extremadamente rico. Sin embargo, hoy hablaremos de la herencia aplicada en la programación orientada a objetos. Si, lo sé, no es algo tan emocionante como recibir una fortuna. Sin embargo es lo que hay. 

Como sabemos. En la programación orientada a objetos. Un objeto es definido por una clase. Esta contiene los métodos y atributos que le dan forma a nuestro objeto. Sin embargo es extremadamente común (sería de hecho muy raro si no) que nuestro objeto comparta ciertas características con otros objetos. Por tanto resulta completamente ineficiente escribir las mismas características y propiedades una y otra vez si al final hacen lo mismo.

Afortunadamente en este paradigma de la programación contamos con un mecanismo que nos permitirá compartir estas características entre nuestros objetos. Este mecanismo es la herencia.

¿Qué es la herencia?

La herencia es un mecanismo de la POO que nos permite pasar atributos y métodos de una clase a otra para así extender su funcionalidad. 

padre hijo y abuelo

En esta relación las clases que ceden sus atributos son conocidas como clases padre o súperclases y las que los reciben son conocidas como clases hijas o subclases. Una clase puede ser hijo y padre al mismo tiempo. Tal como en la vida real somos hijos de nuestro padre, pero nuestro padre a su vez es hijo de nuestro abuelo. 

Esto deriva en un orden jerárquico conocido como jerarquía de clases. (Algo similar al árbol genealógico para nosotros los humanos). 

Jerarquía de Clases

Seguramente hayas escuchado alguna vez que tal persona tiene “los ojos de su abuelo” y la “sonrisa de su madre” Sin embargo nunca habrás escuchado que la abuela sacó los ojos de su nieto. Es simplemente imposible por que la transmisión de la genetica se da siempre en orden descendiente.

En la POO nuestro modelo de abstracción determinará esta jerarquía. De manera que las clases más generales o abstractas irán pasando sus atributos a las clases más especificas. 

inheritance

En el diagrama UML de arriba tenemos un león una vaca y un cerdo. Estos heredan las características de un ser carnívoro, herbívoro y omnívoro respectivamente. Y estos a su vez, heredan sus características de la clase Animal. Por tanto nuestro león, vaca y cerdo parten de ser animales esencialmente; que a medida que acentúan sus diferencias, se vuelven seres completamente distintos. 

Tipos de herencia

Existen básicamente dos tipos de herencia en la programación orientada a objetos.

Herencia Simple

La herencia simple es aquella en la que una clase deriva únicamente de una clase padre (Similar al diagrama presentado en el punto anterior) .

Herencia Múltiple

Esta es una característica de ciertos lenguajes (Python incluido) que permite que una clase pueda heredar características de más de una súperclase.

Creando un pastel con POO

Como tengo hambre. Vamos a crear uno utilizando la programación orientada a objetos y el lenguaje de programación Python.

1. Creamos una clase para definir los ingredientes.

				
					#Define a ingredient.
class Ingredient:
    #Constructor of ingredient
    def __init__(self, name,measure,qty):
        #Name of ingredient
        self.name = name 
        #unit of measurement
        self.measure = measure
        self.qty = qty

				
			

2. Creamos una clase que nos permita construir una lista con todos los ingredientes requeridos. El método addIngredient() tendrá como parámetro la instancia de un objeto de la clase Ingredient

				
					#Define our recipe.
class Recipe: 
    def __init__(self):
        #Empty list that will be populated with ingredients.
        self.listOfIngredients = []


    #Add a new ingredient to recipe.
    def addIngredient(self,ingredient):
        print('adding ' + str(ingredient.qty) + ' ' + ingredient.measure + ' of ' + ingredient.name + '...')
        self.listOfIngredients.append(ingredient)
				
			

4. El pastel a grandes rasgos es una comida. Por lo que crearemos una clase abstracta que nos permita construir cualquier tipo de comida. Aquí empezaremos a utilizar la herencia. Como podemos ver nuestra clase Food esta heredando de la clase Recipe. 

				
					#Abstract class to define food.
class Food(Recipe):

    def __init__(self):
        '''
        It is equal to super(). but because we have multiple inheritance.
        It´s more easy to access in this way.
        '''
        Recipe.__init__(self)
        '''
        We will define the name of our food in the setName() method. 
        So we initialize the name empty.'''
        self.name = None

    #Set name of our food.
    def setName(self,str):
        self.name = str
    
    '''
    This is an abstract method. Because all 
    food must be prepared. However, each one has a 
    different way of preparing. So. In this class 
    we declare the method and in his child classes 
    we implement it.
    '''
    @abstractmethod
    def prepare(self):
        pass
    
    #show our instance
    def serve(self):
        print(self)
				
			

5. Realizamos otra clase abstracta que nos permita definir comida que sea horneada. Su clase padre será Food. Nótese que tenemos el método prepare() y bake() que los recibe de Food y BakedFood respectivamente. 

				
					class BakedFood(Food):
    def __init__(self):
        super().__init__()
    
    @abstractmethod
    def bake(self):
        pass
				
			

6. Creamos la clase que nos permita definir concretamente a nuestro pastel.

				
					class Cake(BakedFood):

    def __init__(self):
        super().__init__()

    def prepare(self):
        #TODO: what is the way to preapre a cake?
        print('preparing a delicious cake...')
    
    def bake(self):
        #TODO: what is the way to bake a cake?
        print('baking amazing cake. wait a few minutes...')
        print('Your cake is ready... Enjoy!')
				
			

7. Ahora si. Construimos nuestro pastel.

				
					#create a new cake
cake = Cake()
#Name of our cake.
cake.setName('Pastel de fresas')
#Add ingredients to our cake.
cake.addIngredient(Ingredient('flour','grams', 800 ))
cake.addIngredient(Ingredient('egg','pieces', 2 ))
cake.addIngredient(Ingredient('strawberry','pieces', 10 ))
cake.addIngredient(Ingredient('milk','mililiters', 200 ))
cake.addIngredient(Ingredient('sugar','grams', 20 ))
cake.addIngredient(Ingredient('butter','grams', 10 ))
cake.addIngredient(Ingredient('salt','grams', 2 ))
cake.addIngredient(Ingredient('baking powder','grams', 20 ))
				
			

Ahora quiero unas papas a la francesa.

¿Cómo es que reutilizamos código utilizando la herencia?. 

Supongamos que en vez de nuestro pastel ahora se nos han antojado unas papas a la francesa.

1. Así como tenemos nuestra clase para comida horneada. Creamos una para comida frita. De igual manera dependera de la clase Food.

				
					class FriedFood(Food):
    def __init__(self):
        super().__init__()
    
    @abstractmethod
    def fry(self):
        pass

				
			

2. También creamos la clase que defina las particularidades de nuestras papas a la francesa.

				
					#Define french fries.
class FrenchFries(FriedFood):
    def __init__(self):
        super().__init__()

    def prepare(self):
        #TODO: what is the way to preapre french fries?
        print('preparing french fries yumi yumi!...')
    
    def fry(self):
        #TODO: what is the way to prepare french fries?
        print('frying our french fries...')
        print('Your french fries are ready... Enjoy!')
				
			

3. Listo. Ya podemos crear nuestras papas a la francesa.

				
					fries = FrenchFries()
fries.addIngredent(Ingredient('salt','grams', 10 ))
fries.addIngredent(Ingredient('potatoe','piece', 1 ))
fries.prepare()
fries.fry()
fries.serve()
				
			

Conclusión

Como puedes ver. La herencia es una gran aliada que nos permitirá desarrollar código de más calidad y de manera más eficiente.

Compartir:
Share on facebook
Facebook
Share on twitter
Twitter
Share on pinterest
Pinterest
Share on linkedin
LinkedIn
Entradas relacionadas
pastel herencia programacion
POO | Entendiendo la herencia de clases

En este artículo desarrollaremos código Puedes consultar el código de esta practica en el siguiente repositorio de github. Generalmente cuando pensamos en herencia. Pensamos en