
On Sun, Apr 03, 2022 at 03:09:18PM -0000, malmiteria wrote:
feature 1 (of super alone): proxying the parent. What most people think super does (and expect it to do): it allows to call method from *the* (most people don't think of multiple inheritance) parent.
For single inheritance, that is exactly what it does, and there is no problem. Just use super() and it Just Works. If you disagree, then please show me an example of *single* inheritance where super does not do the right thing, where each class simply calls its direct parent.
It can be used by working around MRO to proxy any parent directly.
I don't know what you mean by this. Why are you "working around" the MRO? If your class is skipping some of its superclasses, then it is either broken, or you shouldn't be using inheritance for the relationships between the classes.
feature 2 (of super + MRO): sideway specialization / mixins
This is just a form of multiple inheritance where the mixins are not designed to be instantiated themselves.
feature 3 (of super + MRO): dependency injection / inheritance tree alteration
I don't know what you mean by dependency injection here. Dependency injection is one of those Design Patterns beloved by Java developers who over-engineer it into something complicated, but in Python is so trivial that it barely deserves a name. To quote James Shore: “Dependency Injection” is a 25-dollar term for a 5-cent concept. https://www.jamesshore.com/v2/blog/2006/dependency-injection-demystified Inheritance tree modification... I think that means you want to copy a class hierarchy, but with changes? Again, this sounds like inheritance is the wrong tool here. Nnot everything is an inheritance relationship.
feature 4 (of MRO alone): method resolution
This is the one and only thing that super() if for. Well to be precise, its not just methods, but any attributes.
"feature" 5 : diamond problem.
The diamond problem is a feature of multiple inheritance with diamonds. super() can't solve it in the fully general case because there is no general solution.
What motivated me first here was the few problems with the feature 1 (proxying the parent)
What problems? Here you are talking about *the* parent, so we have single inheritance: ``` class Parent: def method(self): print("the parent does stuff") class Child(Parent): def method(self): ... # what problems with super? ``` Please show me what problems you have with super in that simple case of a class with only a single parent class. [...]
class HighGobelin: def scream(self): print("raAaaaAar")
class CorruptedGobelin(HighGobelin): def scream(self): print("my corrupted soul makes me wanna scream") super().scream()
class ProudGobelin(HighGobelin): def scream(self): print("I ... can't ... contain my scream!") super().scream()
class HalfBreed(ProudGobelin, CorrupteGobelin): def scream(self): # 50% chance to call ProudGobelin scream, 50% chance to call CorruptedGobelin scream ```
when writing down the class HalfBreed, we expect the behavior of HalfBreed().scream() to be one of its parent behavior, selected at random with 50% chance each.
Okay.
with the use of super, it could look like that, intuitively
Not it can't. This is wrong. You have misunderstood what super does. What you are doing in this broken class below:
class HalfBreed(ProudGobelin, CorrupteGobelin): def scream(self): if random.choices([True, False]): super(HalfBreed, self).scream() else: super(ProudGobelin, self).scream()
is to try (and fail!) to use inheritance for behaviour which needs to be modelled by delegation. By definition, inheritance requires HalfBreed to call the methods of all three superclasses. (That is at least the definition used in Python, other languages may do differently.) If HalfBreed is not using the methods of all its superclasses, it is not really an inheritance relationship. And you provide the right solution: delegation.
class HalfBreed(ProudGobelin, CorrupteGobelin): def scream(self): if random.choices([True, False]): ProudGobelin.scream(self) else: CorrupteGobelin.scream(self)
Which is an option multiple of you pointed out to me. This options however is flawed in muliple ways, mainly because it looses 3 of the 4 features i describe earlier.
- we lose the proxy feature, which to be fair, is aqueen to syntactic sugar. But this is still a feature loss.
How do you lose a feature you don't want? You don't want to call the parent classes' methods using inheritance. If you did, you would use super, and the HalfBreed would inherit from all three superclasses. But you don't want that, do you do something else. Problem solved.
- we lose the sideway specialisation, coming from super's behavior, which, in this case, is the goal, so we're not complaining.
What sideway specialisation? You have no mixin classes here.
- we lose the possibility of class dependency injection, since today, it relies on a consistent use of super.
No it doesn't. Dependency injection has nothing to do with super. -- Steve