On Thu, Apr 14, 2022 at 10:46:46AM +1200, Greg Ewing wrote:
On 13/04/22 8:29 am, Steven D'Aprano wrote:
When multiple parent provide candidate to a method resolution, raise an error.
Then you aren't doing full MI any more,
That sounds like a "true Scotsman" argument. Who defines what "full MI" means?
If you look at languages that implement MI, and pick the implementations which allow it with the fewest restrictions, then that is "full MI". Class parent/child relationships are not the same as biological relationships: https://www.youtube.com/watch?v=fWQ7TFFKEz8 so I hope that we can agree that excluding cycles and loops in your inheritance hierarchy is a necessary restriction, for our sanity if no other reason. I don't know of any languages that allow cycles in inheritance graphs. Beyond that, I believe that Python (and other languages) allow MI with the smallest set of restrictions, namely that there is a C3 linearization possible: https://en.wikipedia.org/wiki/C3_linearization I believe that those 3 requirements in C3 are the fewest restrictions while still having logically consistent behaviour. That's what I mean by "full MI". Of course languages can impose additional restrictions, e.g. that methods are independent, there there are no diamonds, etc. But they offer less than the full generality that Python (and other languages) offer. For instance, I believe that Eiffel allows MI with diamonds, so long as methods in different branches are independent. If two classes provide the same method, Eiffel raises an exception. (Michele Simionato calls this behaviour equivalent to traits.) That is *more restrictive* than Python, and so it offers *less* than a fully general model of MI. On the other hand, sometimes "less is more", and Michele has come to believe that Python's fully general MI is too powerful to be usable, and that more restrictive versions (traits) are better, or even avoiding inheritance in favour of generics, composition and delegation. We can implement mixins, or traits, or Eiffel-style inheritance, or whatever extra restrictions you want, using decorators or metaclasses. They don't need a change to the language definition of MI.
I can think of at least two languages that do something very similar to what malmalitia is proposing: C++ and (if I remember rightly) Eiffel. I don't think I've heard anyone claim that C++ doesn't do "full MI".
Oooh, ooh, let me sir! "C++ doesn't do full multiple inheritance." If you have to manually call a specific method, as shown here: https://devblogs.microsoft.com/oldnewthing/20210813-05/?p=105554 you're no longer using inheritance, you're doing delegation. I make no comment on whether C++ is justified on restricting inheritance in that way. Michele Simionato declares that C++ implements MI "badly", but I don't know his reason for that judgement. Multiple inheritance is complex. Managing that complexity is hard. It may be that that best way to manage it is to forgo the full generality of MI and all the complexity it brings, or by not using inheritance at all. But either way, Python currently offers MI in its full generality. Restricting it at the language level is a breaking change, and will not happen. -- Steve