On Tue, 29 Mar 2022 at 21:34, Steven D'Aprano <st...@pearwood.info> wrote:
>
> On Tue, Mar 29, 2022 at 06:23:06AM +1100, Chris Angelico wrote:
>
> > 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.
>
> You've never had pizza with cheesy crust *and* cheese as a topping?

That's exactly my point: I don't see this as a conflict. I *like* my
pizza to have all the cheeses!

> > That's not inheritance. That's composition.
>
> I wouldn't call it composition unless it was implemented using
> composition instead of inheritance.
>
> I would call it a *subset* of inheritance.

Hmm, my point is that, if it's considered a conflict, then this isn't
really acting as inheritance. If it's inheritance, then each method is
acting on *the pizza*, but if it's composition, then some methods are
acting on the pizza's crust, and others are acting on the pizza's
toppings.

Ultimately, the difference between composition and inheritance is one
of design, and there are no fundamentally wrong decisions, just
decisions where you might not like the consequences.

But this is why I keep asking for non-toy examples, as it's extremely
hard to discuss design matters when all we have is "class C(A, B):" to
go on.

> That doesn't mean that cooperative MI doesn't have problems. Other
> languages forbid MI altogether because of those problems, or only allow
> it in a severely restricted version, or use a more primitive form of
> super. MI as defined by Python is perhaps the most powerful, but also
> the most potentially complicated, complex, convoluted and confusing.

Agreed, all forms of MI have their problems. Python, by its nature, is
guaranteed to create diamond inheritance with any form of MI (in
contrast, C++ can have MI where two subbranches never intersect, which
has quite different consequences); of all the ways of coping with the
effects of diamond inheritance, the two I've found most useful in
practice are Python's super ("go to the next one, not always up the
hierarchy") and a broad idea of calling every parent (effective, but
needs quite different concepts of cooperation - works well for init
methods though).

The term "cooperative" shouldn't put people off. I've almost never
seen any form of object orientation in which it isn't at least
somewhat cooperative. Some are more loosely coupled than others (IBM's
SOM was an amazingly good system that allowed inheritance from other
people's code, but required a complex build system), but you still
have to follow protocol to make sure your class plays nicely with
others. Most of the time, MI hierarchies are tightly coupled, since
it's extremely difficult to negotiate anything otherwise.

And honestly, I'm fine with that.

ChrisA
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/JESQPVJMPO74VRKIFQWKROIK2LIJJC2W/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to