Herencia múltiple en Python

La herencia es el mecanismo para lograr la reutilización del código, ya que una clase (clase secundaria) puede derivar las propiedades de otra clase (clase principal). También proporciona transitividad, es decir. si la clase C hereda de P, entonces todas las subclases de C también heredarán de P.
 

Herencia múltiple 
Cuando una clase se deriva de más de una clase base, se denomina herencia múltiple. La clase derivada hereda todas las características del caso base.
 

Multiple Inheritance

Syntax:

Class Base1:
       Body of the class

Class Base2:
     Body of the class

Class Derived(Base1, Base2):
     Body of the class

En la próxima sección, veremos el problema que enfrentamos durante la herencia múltiple y cómo abordarlo con la ayuda de ejemplos.
 

El problema del diamante
 

Diamond Probem

Se refiere a una ambigüedad que surge cuando dos clases Clase2 y Clase3 heredan de una superclase Clase1 y la clase Clase4 hereda tanto de Clase2 como de Clase3. Si hay un método «m» que es un método anulado en uno de Class2 y Class3 o ambos, entonces surge la ambigüedad sobre cuál de los métodos «m» Class4 debería heredar.
 

Cuando el método se anula en ambas clases
 

Python3

# Python Program to depict multiple inheritance
# when method is overridden in both classes
 
class Class1:
    def m(self):
        print("In Class1")
       
class Class2(Class1):
    def m(self):
        print("In Class2")
 
class Class3(Class1):
    def m(self):
        print("In Class3") 
        
class Class4(Class2, Class3):
    pass  
     
obj = Class4()
obj.m()

Producción:

In Class2

Nota: cuando llama a obj.m() (m en la instancia de Class4), el resultado es In Class2. Si Class4 se declara como Class4(Class3, Class2), la salida de obj.m() estará en Class3.
 

Cuando el método se anula en una de las clases
 

Python3

# Python Program to depict multiple inheritance
# when method is overridden in one of the classes
 
class Class1:
    def m(self):
        print("In Class1")
       
class Class2(Class1):
    pass
 
class Class3(Class1):
    def m(self):
        print("In Class3")   
      
class Class4(Class2, Class3):
    pass      
 
obj = Class4()
obj.m()

Producción:

In Class3

Cuando cada clase define el mismo método

Python3

# Python Program to depict multiple inheritance
# when every class defines the same method
 
class Class1:
    def m(self):
        print("In Class1")
       
class Class2(Class1):
    def m(self):
        print("In Class2")
 
class Class3(Class1):
    def m(self):
         print("In Class3")    
     
class Class4(Class2, Class3):
    def m(self):
        print("In Class4")  
 
obj = Class4()
obj.m()
 
Class2.m(obj)
Class3.m(obj)
Class1.m(obj)

Producción:

In Class4
In Class2
In Class3
In Class1

La salida del método obj.m() en el código anterior es In Class4 . Se ejecuta el método “m” de Class4. Para ejecutar el método “m” de las otras clases se puede hacer usando los nombres de las clases.
Ahora, para llamar al método m para Class1, Class2, Class3 directamente desde el método «m» de Class4, vea el siguiente ejemplo
 

Python3

# Python Program to depict multiple inheritance
# when we try to call the method m for Class1,
# Class2, Class3 from the method m of Class4
  
class Class1:
    def m(self):
        print("In Class1") 
      
class Class2(Class1):
    def m(self):
        print("In Class2")
 
class Class3(Class1):
    def m(self):
        print("In Class3")    
     
class Class4(Class2, Class3):
    def m(self):
        print("In Class4")  
        Class2.m(self)
        Class3.m(self)
        Class1.m(self)
 
obj = Class4()
obj.m()

Producción:

In Class4
In Class2
In Class3
In Class1

A continuación se muestra cómo llamar a «m» de Class1 desde «m» de Class2 y «m» de Class3 en lugar de Class4:

Python3

# Python Program to depict multiple inheritance
# when we try to call m of Class1 from both m of
# Class2 and m of Class3
 
class Class1:
    def m(self):
        print("In Class1")  
     
class Class2(Class1):
    def m(self):
        print("In Class2")
        Class1.m(self)
 
class Class3(Class1):
    def m(self):
        print("In Class3")
        Class1.m(self)  
      
class Class4(Class2, Class3):
    def m(self):
        print("In Class4")  
        Class2.m(self)
        Class3.m(self)
      
obj = Class4()
obj.m()

Producción:

In Class4
In Class2
In Class1
In Class3
In Class1

La salida del código anterior tiene un problema asociado, el método m de Class1 se llama dos veces. Python proporciona una solución al problema anterior con la ayuda de la función super(). Vamos a ver cómo funciona.
 

La súper función 

Python3

# Python program to demonstrate
# super()
 
class Class1:
    def m(self):
        print("In Class1")
 
class Class2(Class1):
    def m(self):
        print("In Class2")
        super().m()
 
class Class3(Class1):
    def m(self):
        print("In Class3")
        super().m()
 
class Class4(Class2, Class3):
    def m(self):
        print("In Class4")  
        super().m()
      
obj = Class4()
obj.m()

Producción:

In Class4
In Class2
In Class3
In Class1

Super() generalmente se usa con la función __init__ cuando se inicializan las instancias. La súper función llega a una conclusión, sobre qué método llamar con la ayuda de la orden de resolución de métodos (MRO) .
 

Orden de resolución del método:

En Python, cada clase, ya sea integrada o definida por el usuario, se deriva de la clase de objeto y todos los objetos son instancias del objeto de clase. Por lo tanto, la clase de objeto es la clase base para todas las demás clases.
En el caso de la herencia múltiple, primero se busca un atributo determinado en la clase actual; si no se encuentra, se busca en las clases principales. Las clases principales se buscan de izquierda a derecha y cada clase se busca una vez.
Si vemos el ejemplo anterior, el orden de búsqueda de los atributos será Derivado, Base1, Base2, objeto. El orden que se sigue se conoce como linealización de la clase Derivado y este orden se determina mediante un conjunto de reglas llamado Orden de resolución de métodos (MRO).
Para ver el MRO de una clase: 
 

  • Use el método mro(), devuelve una lista, por 
    ejemplo. Clase4.mro()
  • Usa el atributo _mro_, devuelve una tupla 
    Ej. Clase4.__mro__ 
     

Ejemplo: 

Python3

# Python program to demonstrate
# super()
 
class Class1:
    def m(self):
        print("In Class1")
 
class Class2(Class1):
    def m(self):
        print("In Class2")
        super().m()
 
class Class3(Class1):
    def m(self):
        print("In Class3")
        super().m()
 
class Class4(Class2, Class3):
    def m(self):
        print("In Class4")  
        super().m()
      
print(Class4.mro())         #This will print list
print(Class4.__mro__)        #This will print tuple

Producción:

[<clase ‘__principal__.Clase4’>, <clase ‘__principal__.Clase2’>, <clase ‘__principal__.Clase3’>, <clase ‘__principal__.Clase1’>, <clase ‘objeto’>] 
(<clase ‘__principal__. Class4’>, <class ‘__main__.Class2’>, <class ‘__main__.Class3’>, <class ‘__main__.Class1’>, <class ‘object’>) 
 

Publicación traducida automáticamente

Artículo escrito por soumya08 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *