Seite 1 von 1

super in Newstyle-Klassen

Verfasst: Sonntag 18. Juli 2004, 18:50
von Dookie
Hallo zusammen.

Milan stellte in einem Anderen Thread eine Frage zur Verwendung von super in Newstyle-Klassen. Hier will ich mal an einem kleinen Beispiel demonstrieren, was super für Vorteile bietet gegenüber dem Aufruf von Methoden der Elternklasse, wie er in Oldstyle-Klassen bei Mehrfachvererbung vorkommt.
Hier mal ein Beispiel mit Oldstyle:

Code: Alles auswählen

>>> class A:
...:     def __init__(self):
...:         print "__init__ von A"
...:

>>> class B(A):
...:     def __init__(self):
...:         A.__init__(self)
...:         print "__init__ von B"
...:

>>> class C(A):
....:     def __init__(self):
....:         A.__init__(self)
....:         print "__init__ von C"
....:

>>> class D(B,C):
....:     def __init__(self):
....:         B.__init__(self)
....:         C.__init__(self)
....:         print "__init__ von D"
....:
Klasse A ist die Basisklasse, die Klassen B und C sind von A abgeleitet.
Klasse D ist von B und C abgeleitet.
Was passiert nun, wenn wir ein Objekt der Klasse D instanziieren:

Code: Alles auswählen

>>> d = D()
__init__ von A
__init__ von B
__init__ von A
__init__ von C
__init__ von D
Wie zu sehen ist, wird __init__ von A zweimal aufgerufen. Das kann leicht zu seltsamen Verhalten von Merhoden führen und ist nur mit extra Aufwand zu umgehen.

versuchen wir das ganze mal mit Newstyle-Klassen und super:

Code: Alles auswählen

>>> class A(object):
....:     def __init__(self):
....:         super(A,self).__init__()
....:         print "__init__ von A"
....:

>>> class B(A):
....:     def __init__(self):
....:         super(B,self).__init__()
....:         print "__init__ von B"
....:

>>> class C(A):
....:     def __init__(self):
....:         super(C,self).__init__()
....:         print "__init__ von C"
....:

>>> class D(B, C):
....:     def __init__(self):
....:         super(D,self).__init__()
....:         print "__init__ von D"
....:
Schauen wir jetzt mal was passiert wenn wir D instanziieren:

Code: Alles auswählen

>>> d = D()
__init__ von A
__init__ von C
__init__ von B
__init__ von D
Jetzt wird __init__ von A nur noch einmal aufgerufen.

Dies ist nur ein Aspekt von super. Ein anderer ist, wie aus der Syntax zu sehen, wird an super als erster Parameter die Klasse übergeben, deren Elternklasse(n) angesprochen werden sollen. Jetzt kann, ohne im restlichen Code Änderungen zu machen, auch mal eine andere Klasse als Elternklasse verwendet werden.

In __init__-Methode der Klasse A könnte der Superaufruf von __init__ auch wegbleiben. Ich mache es aber auch bei Klassen die von z.B. object abgeletet sind, da ich dann bei späteren Änderungen an der Klasse auch eine andere Basisklasse eintragen kann ohne sonstwo im Code etwas anpassen zu müssen.


Gruß

Dookie