Funcion super()

Hernán Martínez Foffani hernan en orgmf.com.ar
Mar Oct 26 17:17:11 CEST 2004


> class A(object):
>   def meth(self):
>     print "A"
>
> class B(A):
>   def meth(self):
>     print "B"
>     super(B,self).meth()
>
> class C(A):
>   def meth(self):
>     print "C"
>     super(C,self).meth()
>
> class D(B,C):
>   def meth(self):
>     print "D"
>     super(D,self).meth()
>
>  >>> d=D()
>  >>> d.meth()
> D
> B
> C
> A
>
> es dedir, con un super(...).meth() se llama el método de las dos (!)
> clases bases. (He leído alguna vez algo sobre clases cooperativas.)

Lo que pasa es que llamas a super en cada metodo de las superclases
(eso es lo que las hace cooperativas.)

Si cada superclase invoca a super obtienes lo que muestras en
tu ejemplo y esa es la ventaja de super, que te permite recorrer el
grafo solo una vez.

El caso de uso es cuando queremos extender la funcionalidad de un metodo.
Lo que normalmente hacemos es reemplazar ese metodo y en el metodo
reemplazado
programamos nuestra especializacion e invocamos al metodo base
(o al reves, primero invocamos al metodo base y luego especializamos).

En herencia simple daría lo mismo decir
    def meth():
      print "B"
      super(B,self).meth()
que
    def meth():
      print "B"
      A.meth(self)

pero en el caso de herencia multiple (con la jerarquía de tu ejemplo)
si usáramos la forma tradicional deberíamos hacer (para D, B y C
respectivamente) algo como:

    def meth():           def meth():             def meth():
      print "D"             print "B"               print "C"
      B.meth(self)          A.meth(self)            A.meth(self)
      C.meth(self)

El resultado es que A.meth(self) se llama ¡DOS VECES!


B y C son clases cooperativas porque para invocar al
metodo sobreescrito de la clase base (A) utilizan super.

En una jerarquía de clases de tipo herencia simple
tanto B como C funcionan igual si llamaran a A.meth(), es decir que
no habría diferencias para instancias de B o C si usan la primera
o la segunda forma.

Puede parecer curioso y es dificil de ver a primera vista, pero
si en tu ejemplo B no utilizara super y llamara a la superclase
con A.meth(self) el resultado es que se saltea ¡C!
super asegura el recorrido de la cadena de llamados.

En definitiva, son cooperativas porque permiten que un tercero
D pueda heredar de *ambas*.  Si todas utilizan super, el grafo
se recorre una vez para toda la jerarquía.

-H.




Más información sobre la lista de distribución Python-es