Herencia

Python SELF ES
Nivel 15 , Lección 6
Disponible

6.1 La herencia es simple

La herencia es un concepto fundamental de la programación orientada a objetos (OOP), que permite a una clase (llamada clase hija o subclase) heredar campos y métodos de otra clase (llamada clase padre o superclase).

Este enfoque permite crear clases más generales y reutilizar código, mejorando la organización y mantenibilidad del código.

¿Por qué necesitamos la herencia?

Supongamos que necesitas escribir algún código y decides hacerlo en forma de una clase. Entonces descubres que en tu proyecto ya existe una clase que hace casi todo lo que necesitas en tu clase. Puedes simplemente copiar el código de esa clase en la tuya y usarlo a tu antojo.

O puedes "como que copiarlo". Puedes declarar esa clase como padre de tu clase, y entonces Python añadirá a tu clase el comportamiento de la clase padre.

Imagínate que eres la naturaleza y quieres crear un Perro. ¿Qué será más rápido: crear un perro a partir de una bacteria en mil millones de años o domesticar un lobo en 200 mil años?

Ejemplo de herencia básica

Supongamos que tienes una clase padre Animal con un campo name:


class Animal:
    def __init__(self, name):
        self.name = name

Queremos crear 2 clases heredadas de él — Dog y Cat, y además agregarles a ambos el método speak:


class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"

En el ejemplo anterior, las clases hijas Dog y Cat heredan de Animal y agregan el método speak.

La clase Dog:

  • Heredó el atributo name de Animal.
  • Agrega el método speak, que devuelve una cadena específica para perros.

La clase Cat:

  • Heredó el atributo name de Animal.
  • Agrega el método speak, que devuelve una cadena específica para gatos.

La versión final del código se ve así:


class Animal:
    def __init__(self, name):
        self.name = name
         
class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"
        
class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"
         
dog = Dog("Buddy")
cat = Cat("Whiskers")
        
print(dog.speak())  # Mostrará: Buddy says Woof!
print(cat.speak())  # Mostrará: Whiskers says Meow!

En este ejemplo, Animal es la clase padre, y Dog y Cat son las clases hijas. Las clases hijas heredan el atributo name y el método __init__ de la clase padre Animal, pero agregan los métodos speak.

6.2 Lo que hay detrás de la herencia

Si le añades un padre a tu clase, es muy similar a como si hubieras copiado el código de la clase padre dentro de tu clase.


class Animal:
    def __init__(self, name):
        self.name = name
         

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)  # Llamada al constructor de la clase padre
        
    def speak(self):
        return f"{self.name} says Woof!"
        
class Cat(Animal):
    def __init__(self, name):
        super().__init__(name)  # Llamada al constructor de la clase padre
        
    def speak(self):
        return f"{self.name} says Meow!"
        

dog = Dog("Buddy")
cat = Cat("Whiskers")
        
print(dog.speak())  # Mostrará: Buddy says Woof!
print(cat.speak())  # Mostrará: Whiskers says Meow!

Esto no es una descripción completamente precisa, pero si nunca has enfrentado el concepto de herencia, puedes pensar en ello de esta manera por ahora. Luego agregaremos más detalles.

6.3 Jerarquía de herencia

Muy a menudo, cuando diseñas un modelo complejo de un gran grupo de clases, puedes encontrarte con toda una jerarquía de herencia.

Por ejemplo, tienes una clase Animal — es la clase base para todos los animales:


class Animal:
    def __init__(self, name):
        self.name = name
        
    def speak(self):
        raise NotImplementedError("Subclass must implement abstract method")

Incluso le hemos añadido un método speak, pero como un animal abstracto no habla, este método simplemente lanza la excepción NotImplementedError — esto es una práctica estándar.

Luego, añadimos clases intermedias que corresponden a categorías de animales: Mammal — que son mamíferos y Bird para las aves.


class Mammal(Animal):
    def __init__(self, name, fur_color):
        super().__init__(name)  # Llamada al constructor de la clase padre
        self.fur_color = fur_color
         

class Bird(Animal):
    def __init__(self, name, wing_span):
        super().__init__(name)  # Llamada al constructor de la clase padre
        self.wing_span = wing_span
        
    def fly(self):
        return f"{self.name} is flying with a wingspan of {self.wing_span} meters."

Y finalmente, solo en la etapa final aparecen las clases de tipos específicos de animales:


class Dog(Mammal):
    def speak(self):
        return f"{self.name} says Woof!"
         
        
class Cat(Mammal):
    def speak(self):
        return f"{self.name} says Meow!"
        
class Parrot(Bird):
    def speak(self):
        return f"{self.name} says Squawk!"

Normalmente con ellos trabaja el código final:


animals = [Dog("Buddy", "brown"), Cat("Whiskers", "white"), Parrot("Polly", 0.5)]
            
for animal in animals:
    print(animal.speak())

print(f"{dog.name} has {dog.fur_color} fur.")  # Mostrará: Buddy has brown fur.
print(f"{cat.name} has {cat.fur_color} fur.")  # Mostrará: Whiskers has white fur.
print(parrot.fly())  # Mostrará: Polly is flying with a wingspan of 0.5 meters.

Aunque técnicamente no hay prohibiciones para crear jerarquías con docenas de ancestros, es importante recordar que, a menos que sea necesario, es mejor mantenerse simple. En la simplicidad está la fuerza.

2
Tarea
Python SELF ES, nivel 15, lección 6
Bloqueada
Vehículos.
Vehículos.
2
Tarea
Python SELF ES, nivel 15, lección 6
Bloqueada
Figuras.
Figuras.
1
Cuestionario/control
Clases y OOP, nivel 15, lección 6
No disponible
Clases y OOP
Clases y OOP
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION