
On Tue, 29 Mar 2022 at 06:12, malmiteria <martin.milon@ensc.fr> wrote:
Steven D'Aprano writes:
How else are you going to get inheritance without a linear order? The interpreter can only call superclass methods one at a time, in some linear order.
You can decide what method should be the one resolved to *after* visiting all superclass methods.
I've already implemented it here, it's a "simple" recursion (no recursion is ever simple xD): https://github.com/malmiteria/super-alternative-to-super/blob/59ff90029db6e4...
Lots of checking of __dict__ here - what happens if it has __slots__?
Essentially, as long as parent don't have it, you keep looking higher in the inheritance tree, either you find no such method, and you raise an AttributeError, if you found it only once, you return it, and if you found multiple, you raise the ExplicitResolutionRequired error.
The order in which you visited the parent is irrelevant to the result, what matters is only to stop exploring a branch when it ends, or when you found the method. Each parent is looked up in its own branch, independantly of any other branches.
The end result is absolutely not affected by the order in which you've explored those branches
Okay, this is definitely looking like what I was saying about a pizza inheriting from its crust and toppings. If I'm reading this correctly, you're defining a "conflict" as finding two implementations of the same-named method in independent subtrees of inheritance - that is, when you say "class Pizza(Crust, Topping):", you're treating Crust and Topping as completely independent, and if they both define an add_cheese method, that's a conflict. That's not inheritance. That's composition.
The whole point of inheritance is that (to the degree that it is possible) we should not explicitly care about where the methods are defined
Agreed. My solution doesn't require you to be explicit about where a method is defined. It only eventually raises an error in case of collision, which you can resolve by redefining the method in the child class, only if you intend on calling it (not calling a method that would raise an error is fine with my solution, whereas current MRO + super fails at class definition time no matter your use of that class). my __as_parent__ allows to explicitely call each one of the parents method individually wherever it matters to you
--
If you do want to explicitly specify where the methods are defined
I don't, at least that's not what my solution is for / requires you to do.
--
If you want to manage your "inheritance" manually by specifying the order, then just don't use automatic inheritance
That's what i have to resolve to today yeah. The feature has its limits, working around it is painful, that's why i'm proposing this change to the language
If you want to make a semi-cooperative way to look up methods in either of several components, I'd look at something like this: @pass_along class Pizza: __components__ = Crust, Topping where the pass_along decorator adds a __getattr__ method that basically goes "does this component have it? does this component have it?" and then resolves conflicts accordingly. That way, external callers can refer to Pizza methods as if they are the union of all Crust and Topping methods, but without the issues of confusing behaviour that changing the definition of inheritance gives. ChrisA