[Python-es] herencia multiple comportamiento con diferentes argumentos

Chema Cortes pych3m4 en gmail.com
Jue Ago 23 06:21:51 EDT 2018


El jue 23/08/2018, 4:46, AGTUGO <agtugo en gmail.com> escribió:
>
> La implementación en scala se puede leer muy fácilmente sin conocer el
lenguaje. Es interesante ver cómo hay varios lenguajes para la jvm, lástima
que jython nunca despegó del todo. de conclusión de esto es que no me
encanta super() ya que solo es un next del mro casi como si fuera un
iterador. Veré cómo lo hace smalltalk ya que siempre es interesante ver
cómo implementan cosas.
>
> El caso donde me parece útil usar un adaptador, es cuando usas una clase
que no puedes modificar y aunque no haya sido pensada así .
>
> class Moveable:
>     def __init__(self, x, y):
>         self.x = x
>         self.y = y
>     def draw(self):
>         print('Drawing at position:', self.x, self.y)
>
>
>
> class MoveableAdapter(Root):
>     def __init__(self, x, y, **kwds):
>         self.movable = Moveable(x, y)
>         super().__init__(**kwds)
>     def draw(self):
>         self.movable.draw()
>         super().draw()
>
> class MovableColoredShape(ColoredShape, MoveableAdapter):
>     pass
>
> MovableColoredShape(color='red', shapename='triangle',
>                     x=10, y=20).draw()
>
> Solo me parece útil cuando por alguna razón no puedes modificar esas
clases. Por ejemplo: trabajo cooperativo o arquitectura dependiente de la
clase que no quieres modificar. No sé si sea lo más elegante pero me parece
práctico.

Tal como te decía, el adaptador debe adaptar todos los métodos, no basta
con el método __init__.

Imagina que ColoredShape cambia la signatura del método draw y que
MovableColoredShape lo defines al revés:

class MovableColoredShape( MoveableAdapter, ColoredShape ):
     pass

Cuando el adaptador invoque el método draw del super dará error, porque la
clase ColoredShape espera argumentos que no le estaría pasando.

>
> ____________________________________________________________________
> El mar., 14 de ago. de 2018 6:41 PM, Chema Cortes <pych3m4 en gmail.com>
escribió:
>>
>>
>>
>> El lun., 13 ago. 2018 a las 16:58, AGTUGO (<agtugo en gmail.com>) escribió:
>>>
>>> Después de estudiar tu respuesta Chema, cómo dices kwargs es necesario.
Y después de revisar la documentación de Python hace referencia a esta
excelente guía
https://rhettinger.wordpress.com/2011/05/26/super-considered-super/
>>>
>>> Pone ejemplos de cómo usar adaptadores para clases que no están
diseñadas para ser cooperativas, y el adaptador puede ser la clase base que
sea necesaria. Como dices **kwargs es la única manera.
>>>
>>> Si no puedes modificar la clase de la cual quieres heredar de manera
multiple y no esta diseñada para ser cooperativa; pues un adaptador y ya
está.
>>>
>>
>> Si el fin de usar herencia múltiple era tener código más fácil de
reutilizar y mantener, precisamente los adaptadores consiguen el efecto
contrario. En el ejemplo que has puesto, no sólo habría que adaptar el
método __init__, sino también, por si acaso, los demás métodos heredados
como sería el método 'draw'. Además está el problema de las clases
colaborativas a medias, aquellas que usan 'super' para propagar la cadena
de llamadas, pero que en sus métodos no han considerado usar kwargs. Los
adaptadores no sirven para estos casos.
>>
>> No sabría darte una solución general que valga en todos los casos. Por
comparar, pongo un gist con la reescritura en scala del mismo ejemplo.
Scala no tiene herencia múltiple, por lo que hay que ser explícito en el
orden de llamadas de los métodos heredados. Al menos los errores se
corrigen antes de ejecutar el código:
>>
>>     https://gist.github.com/chemacortes/f1796931088e406060543894c9f45d52
>>
>>
>> --
>> Hyperreals *R  "Quarks, bits y otras criaturas infinitesimales":
https://blog.ch3m4.org
>> Buscador Python Hispano: http://busca.ch3m4.org
>> _______________________________________________
>> Python-es mailing list
>> Python-es en python.org
>> https://mail.python.org/mailman/listinfo/python-es
>
> _______________________________________________
> Python-es mailing list
> Python-es en python.org
> https://mail.python.org/mailman/listinfo/python-es
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.python.org/pipermail/python-es/attachments/20180823/8c418aaa/attachment.html>


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