Niestety, nie ma sposobu, aby to robić przy użyciu super()
bez zmiany klas bazowych. Wszelkie wywołanie konstruktorów dla B
lub C
ma zamiar spróbować zadzwonić do następnej klasy w Method Resolution Order, który zawsze będzie B
lub C
zamiast klasy A
że klasa konstruktorzy B
i C
przyjąć.
Alternatywą jest jawne wywoływanie konstruktorów bez użycia super()
w każdej klasie.
class A(object):
def __init__(self, a):
object.__init__()
self.a = a
class B(A):
def __init__(self, a, b):
A.__init__(self, a)
self.b = b
class C(object):
def __init__(self, a, c):
A.__init__(self, a)
self.c = c
class D(B, C):
def __init__(self, a, b, c, d):
B.__init__(self, a, b)
C.__init__(self, a, c)
self.d = d
Jest jeszcze minusem tutaj jako konstruktor A
byłoby nazwać dwukrotnie, których tak naprawdę nie ma większego wpływu w tym przykładzie, ale może powodować problemy w bardziej złożonych konstruktorów. Możesz dołączyć sprawdzanie, aby uniemożliwić działanie konstruktora więcej niż jeden raz.
class A(object):
def __init__(self, a):
if hasattr(self, 'a'):
return
# Normal constructor.
Niektórzy nazywają to niedociągnięcie super()
, i to jest w pewnym sensie, ale to też tylko niedociągnięcie w wielokrotnego dziedziczenia w ogóle. Diamentowe wzorce dziedziczenia są często podatne na błędy. Wiele z tych obejść prowadzi do jeszcze bardziej mylącego i podatnego na błędy kodu. Czasami najlepszą odpowiedzią jest próba naprawy kodu i użycie mniejszego dziedziczenia.
Możliwy duplikat [W jaki sposób działa super() Pythona w przypadku dziedziczenia wielokrotnego?] (Http://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with-multiple-initance) – erip
ty można dwukrotnie wywołać '__init__' dla' B' i 'C'. – sobolevn
Ale wtedy 'A .__ init__' będzie wywoływany dwa razy, prawda? – user5459381