Polimorfismo

El polimorfismo es una propiedad de la herencia por la que objetos de distintas subclases pueden responder a una misma acción.

La polimorfia es implícita en Python, ya que todas las clases son subclases de una superclase común llamada Object.

Por ejemplo, la siguiente función aplica una rebaja al precio de un producto:

def rebajar_producto(producto, rebaja):
    producto.pvp = producto.pvp - (producto.pvp/100 * rebaja)

 

Gracias al polimorfismo no tenemos que comprobar si un objeto tiene o no el atributo pvp (precio de venta al público.), simplemente intentamos acceder y si existe premio:

print(alimento, "\n")
rebajar_producto(alimento, 10)
print(alimento)
 
REFERENCIA      2035
NOMBRE          Botella de Aceite de Oliva
PVP             5
DESCRIPCIÓN     250 ML
PRODUCTOR       La Aceitera
DISTRIBUIDOR    Distribuciones SA
 
REFERENCIA      2035
NOMBRE          Botella de Aceite de Oliva
PVP             4.5
DESCRIPCIÓN     250 ML
PRODUCTOR       La Aceitera
DISTRIBUIDOR    Distribuciones SA

 

Como se puede ver en el ejemplo, cuando modificamos un atributo de un objeto dentro de una función éste cambia en la instancia. Esto es por aquello lo que vimos respecto al pasar valor y referencia.

 

Copia de objetos

De la misma forma que las colecciones, los objetos se pasan a las funciones por referencia. Si modificamos sus valores dentro, éstos se verán reflejados fuera.

Esto también afecta a la hora de hacer copias, creándose en su lugar un acceso al objeto en lugar de uno nuevo con sus valores:

class Test:
    pass
 
test1 = Test()
test2 = test1
 
test1.algo = "Prueba"
 
print(test2 == test1)  # ¿Son el mismo objeto?
 
try:
    print(test2.algo)
except Exception as e:
    print(e)
True
Prueba
 

Para realizar una copia a partir de sus valores podemos utilizar la función copy del módulo con el mismo nombre:

from copy import copy
 
class Test:
    pass
 
test1 = Test()
test2 = copy(test1)
 
test1.algo = "Prueba"
 
print(test2 == test1)  # ¿Son el mismo objeto?
 
try:
    print(test2.algo)
except Exception as e:
    print(e)
False
'Test' object has no attribute 'algo'
 

La función copy se puede utilizar también para copiar colecciones:

from copy import copy
 
lista1 = [1,2,3]
lista2 = copy(lista1)
lista1 = None
 
print(lista1)
print(lista2)
 
None
[1, 2, 3]

 

Herencia múltiple

Finalmente hablemos de la herencia múltiple: la capacidad de una subclase de heredar de múltiples superclases.

Esto conlleva un problema, y es que si varias superclases tienen los mismos atributos o métodos, la subclase sólo podrá heredar de una de ellas.

En estos casos Python dará prioridad a las clases más a la izquierda en el momento de la declaración de la subclase:

class A:
    def __init__(self):
        print("Soy de clase A")
    def a(self):
        print("Este método lo heredo de A")
 
class B:
    def __init__(self):
        print("Soy de clase B")
    def b(self):
        print("Este método lo heredo de B")
 
class C(B,A):
    def c(self):
        print("Este método es de C")
 
 
c = C()
c.a()
c.b()
c.c()
Soy de clase B
Este método lo heredo de A
Este método lo heredo de B
Este método es de C