Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is that OK to use the MRO in order to override a mixin?

Problem description: I have a class C inheriting from mixins A and B. I want a new class, C_, having all the methods/attributes defined in the class C but with B swapped with B_ (same API) in the inheritance scheme (one possible use of this is easy mocking). All classes are new style classes.

I got what I wanted by messing with the inheritance order, therefore the MRO:

A   B   B_    B_  A   B
 \ /   /       \   \ /
  C   /         \   C
   \ /           \ /
    C1            C2
C1(C,B_)       C2(B_,C)

C1.__mro__ = (C1, C , A, B, B_, object)
C2.__mro__ = (C2, B_, C, A, B , object)

The C2 method (inheriting the modified mixin before the C class) works without much surprise and if I call a method defined in the B mixin, the B_'s definition is chosen.

For the moment it works, but I feel like: "fingers crossed, I hope a special case does not arise and break the system !"

The question is: is it a finally-not-so-wrong way to solve the problem or is there a better way to do it ?

PS: I think I could take my bazooka and create a metaclass to redefine the mro (as said in the official doc), but my instinct says it's not going to be necessarily prettier.

like image 499
Cranium Avatar asked Feb 01 '15 19:02

Cranium


1 Answers

Your approach should work just fine. It is legitimate to use a subclass to control the MRO and to shadow one class with another.

This blog post gives several examples: https://rhettinger.wordpress.com/2011/05/26/super-considered-super/

like image 186
Raymond Hettinger Avatar answered Sep 18 '22 16:09

Raymond Hettinger