[issue38262] Mixins - super calls in bases of multiple-inheritance with different parameters

Arno-Can Uestuensoez report at bugs.python.org
Tue Sep 24 23:45:13 EDT 2019


Arno-Can Uestuensoez <acue.opensource at gmail.com> added the comment:

Hi,
first of all thank you both for the fast reply.

The point is here, that the call routing and the parameter passing are intermixed. The MRO defines the call order, but does not define a signature change for the call within one inheritance layer.

All articles I found including the mentioned blog-post(https://rhettinger.wordpress.com/2011/05/26/super-considered-super/) deal with the call order. But as far as I can see all imply silently the correctness of the call signatures defined by the derived classes - see also https://en.wikipedia.org/wiki/Object-oriented_programming#Polymorphism.

Well, this is so common for me since about 1990, that I even have to think about how to explain.

The simple diagram of the basic 4-class diamond depicts the call routing and the call signatures - see
https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem.

The class hierarchy is

        A
        |
    +---+---+
    |       |
    B       C
    |       |
    +---+---+
        |
        D

with the classes

   A or more precise A(object)
   B(A)
   C(A)   
   D(B, C)
   
The resulting call routing MRO/C3 linearization - https://en.wikipedia.org/wiki/C3_linearization - is:

   D -> B -> C -> A

See https://en.wikipedia.org/wiki/Multiple_inheritance#Mitigation, and https://www.python.org/download/releases/2.2.3/descrintro/#mro.

This basic diamond structure represents the call signatures:

   I:   for D
   II:  for B and C
   III: for D

The call signature of a given method interface for the implementation of class D has to be equally defined by the classes B *AND* C! Which means has to be the same - ignoring defaults here. This is how OO works. Though the called signatures of the classes B *AND* C has to be identical too! Which is completely independent from the dynamic call order - but defined by the static inheritance graph.

This is in particular true due to the fact, that the single inheritance call signatures has to be identical too

   D(B).mthX() == D(C).mthX()

or in general - related to the call signatures the following interface calls are defined to have equal call parameters(ignoring defaults here):

   D(B,C).mthX() == D(C,D).mthX() == D(B).mthX() == D(C).mthX()

Anything else is an error.

The current implementation changes the routed method calls to the following call signatures:

   I:   for D
   II:  for B
   III: for C and D

So this is not just an inconvenience as you mentioned. It is simply a bug.

----------
resolution: not a bug -> postponed
Added file: https://bugs.python.org/file48625/mixin_C_is_B0A1.py

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue38262>
_______________________________________


More information about the Python-bugs-list mailing list