Inherit same function name from several classes
Question:
I was reading on this thread on stackoverflow but it looked like the solution was wrong according to a user and most important, it couldnt solve my question and I dont know if its because the answer is in python 2 or whatnow.
However, lets say i have this code
class A:
def say_hello(self):
print("Hi")
class B:
def say_hello(self):
print("Hello")
class C(A, B):
def say_hello(self):
super().say_hello()
print("Hey")
welcome = C()
welcome.say_hello()
How can i call both class A and B from class C without changing the names of the functions?
As i read in the other thread you could do something like super(B, self).say_hello()
but that does not seem to work, I dont know why though.
Answers:
To use super
properly, every class involved needs to be designed correctly. Among other things:
-
One class should be the “root” for the method, meaning it will not use super
to delegate calls further. This class must appear after any other class providing the method.
-
All classes that are not the root must use super
to pass call the method from any other class that might define the method.
# Designated root class for say_hello
class A:
def say_hello(self):
print("Hi")
# Does not inherit say_hello, but must be aware that it is not the root
# class, and it should delegate a call further up the MRO
class B:
def say_hello(self):
super().say_hello()
print("Hello")
# Make sure A is the last class in the MRO to ensure all say_hello
# methods are called.
class C(B, A):
def say_hello(self):
super().say_hello()
print("Hey")
welcome = C()
welcome.say_hello()
Here, super
in C.say_hello
will call B.say_hello
, whose super
will call A.say_hello
.
If you don’t want go along with the requirements for using super
, just call the other class’s methods explicitly. There is no requirement to use super
.
class A:
def say_hello(self):
print("Hi")
class B:
def say_hello(self):
print("Hello")
class C(A, B):
def say_hello(self):
A.say_hello(self)
B.say_hello(self)
print("Hey")
If you don’t want to decide which class (A or B) is the designated root class, you can also implement an abstract superclass for both A and B.
from abc import ABC, abstractmethod
class ISayHello(ABC):
@abstractmethod
def say_hello(self):
pass
class A(ISayHello):
def say_hello(self):
super().say_hello()
print("Hi")
class B(ISayHello):
def say_hello(self):
super().say_hello()
print("Hello")
class C(B,A):
def say_hello(self):
super().say_hello()
print("Hey")
welcome_c = C()
welcome_c.say_hello()
This would make sense if you have an additional class D with different root class than C.
class D(A,B):
def say_hello(self):
super().say_hello()
print("Hey")
welcome_d = D()
welcome_d.say_hello()
I was reading on this thread on stackoverflow but it looked like the solution was wrong according to a user and most important, it couldnt solve my question and I dont know if its because the answer is in python 2 or whatnow.
However, lets say i have this code
class A:
def say_hello(self):
print("Hi")
class B:
def say_hello(self):
print("Hello")
class C(A, B):
def say_hello(self):
super().say_hello()
print("Hey")
welcome = C()
welcome.say_hello()
How can i call both class A and B from class C without changing the names of the functions?
As i read in the other thread you could do something like super(B, self).say_hello()
but that does not seem to work, I dont know why though.
To use super
properly, every class involved needs to be designed correctly. Among other things:
-
One class should be the “root” for the method, meaning it will not use
super
to delegate calls further. This class must appear after any other class providing the method. -
All classes that are not the root must use
super
to pass call the method from any other class that might define the method.
# Designated root class for say_hello
class A:
def say_hello(self):
print("Hi")
# Does not inherit say_hello, but must be aware that it is not the root
# class, and it should delegate a call further up the MRO
class B:
def say_hello(self):
super().say_hello()
print("Hello")
# Make sure A is the last class in the MRO to ensure all say_hello
# methods are called.
class C(B, A):
def say_hello(self):
super().say_hello()
print("Hey")
welcome = C()
welcome.say_hello()
Here, super
in C.say_hello
will call B.say_hello
, whose super
will call A.say_hello
.
If you don’t want go along with the requirements for using super
, just call the other class’s methods explicitly. There is no requirement to use super
.
class A:
def say_hello(self):
print("Hi")
class B:
def say_hello(self):
print("Hello")
class C(A, B):
def say_hello(self):
A.say_hello(self)
B.say_hello(self)
print("Hey")
If you don’t want to decide which class (A or B) is the designated root class, you can also implement an abstract superclass for both A and B.
from abc import ABC, abstractmethod
class ISayHello(ABC):
@abstractmethod
def say_hello(self):
pass
class A(ISayHello):
def say_hello(self):
super().say_hello()
print("Hi")
class B(ISayHello):
def say_hello(self):
super().say_hello()
print("Hello")
class C(B,A):
def say_hello(self):
super().say_hello()
print("Hey")
welcome_c = C()
welcome_c.say_hello()
This would make sense if you have an additional class D with different root class than C.
class D(A,B):
def say_hello(self):
super().say_hello()
print("Hey")
welcome_d = D()
welcome_d.say_hello()