hm, was bedeutet das eigentlich genau?
was würde nicht gehen, wenn diese überladung nicht möglich wäre?
und vor allem: warum findet eine überladung bei der verwendung des __init__ konstruktors statt, wie vielfach geschrieben wird, oder wann findet sie konkret statt, oder findet sie tatsächlich immer statt???
ich bin etwas verwirrt
mfg
roland
Überladung von Operatoren
Überladen von Methoden heißt in dem Fall 'Überschreiben der entsprechendenden Elternmethoden'. Operatorüberladung ist das Überschreiben spezieller Methoden. Diese speziellen Methoden werden gerifen, wenn ein Operator auftritt.
Ich kann mir z.B. beliebige komplexe Objekte basteln, und mit Operatorüberladung definieren,w as passieren soll, wenn ich z.B. zwei dieser Objekte mittels '+' addiere.
Ich kann also dem Operator '+' in Verbindung mit meinen Objekten einen eigenen, von mir bestimmten Sinn geben.
Natürlich geht das auch für andere Operatoren.
Jörg
Ich kann mir z.B. beliebige komplexe Objekte basteln, und mit Operatorüberladung definieren,w as passieren soll, wenn ich z.B. zwei dieser Objekte mittels '+' addiere.
Ich kann also dem Operator '+' in Verbindung mit meinen Objekten einen eigenen, von mir bestimmten Sinn geben.
Natürlich geht das auch für andere Operatoren.
Jörg
kannst du mir das mal konkret darstellen?
heisst das weil ich z.b auch zwei strings mit + verbinden kann?
und was hat es mit der überladung des konstruktors auf sich?
heisst das weil ich z.b auch zwei strings mit + verbinden kann?
und was hat es mit der überladung des konstruktors auf sich?
Der Konstruktor (__init__) kann wie jede andere Methode auch überladen/überschrieben werden. Meist will man aber, daß der Elternkonstruktor trotzdem ausgeführt wird, und der Kindkonstruktor nur zusätzlich. Dann muß man den Elternkonstruktor explizit innerhalb des Kindkonstruktors aufrufen:rolgal hat geschrieben:kannst du mir das mal konkret darstellen?
heisst das weil ich z.b auch zwei strings mit + verbinden kann?
und was hat es mit der überladung des konstruktors auf sich?
Code: Alles auswählen
class A:
def __init__(self, a):
self.a = a
class B(A):
def __init__(self, a, b):
A.__init__(self, a)
self.b = b
Nun wäre es doch praktisch, wenn Du mit Instanzen dieser Klasse ganz normale Operationen durchführen kannst, wobei Einheiten automatisch konvertiert werden sollen. Also definierst Du für Deine Klasse eine Methode '__add__'.
Diese Methode bekommt als Argumente sich selbst und den Operationspartner. Innerhalb der Methode kannst Du nun den Typ auswerten: Instanz + Instanz geht, Instanz plus float oder int geht auch, sonst geht es nicht. Der Returnwert ist das Ergebnis der Addition, also eine neue Instanz deiner Klasse.
Ab sofort kannst Du einfach "A+B" schreiben, wobei A und B Instanzen deiner ZahlMitEinheit-Klasse ist. Python erkennt,
daß es diese Methode benutzen soll, um diese Instanzen zu addieren.
Genauso gehts Du noch für Subtraktion, Multiplikation ... usw. vor.
Natürlich kann man damit auch Blödsinn machen. Also eine Klasse definieren, die sich wie ein Integer verhält, aber bei '-' immer addiert statt subtrahiert...
Ich hoffe, das war jetzt etwas klarer.
Jörg
ich habe das schon mal gefragt.....
ehrlich gesagt versteh ich es nur bedingt.
aber eigentlich auch egal, meistens erschliessen sich die sachen, wenn man sie wirklich braucht.
das mit dem konstruktor habe ich hoffentlich verstanden: er wird nur dann überladen, wenn in der subklasse der konstruktor der elternklasse aufgerufen wird, oder?
mfg
roland
ehrlich gesagt versteh ich es nur bedingt.
aber eigentlich auch egal, meistens erschliessen sich die sachen, wenn man sie wirklich braucht.
das mit dem konstruktor habe ich hoffentlich verstanden: er wird nur dann überladen, wenn in der subklasse der konstruktor der elternklasse aufgerufen wird, oder?
mfg
roland
Ich glaube hier verwechselst du zwei verschiedene Sachen, oder? Methoden (wozu auch der Konstruktor gehöhrt) werden beim Ableiten von anderen Klassen vererbt, es sei denn sie werden überdefiniert (also quasi neu geschrieben). Wenn du das mit dem konstruktor tust, kannst du den Konstruktor der alten Klasse an deiner neuen Klasse rufen. Bsp:
Das andere ist das überladen von Operatoren. Hier definierst du was beim addieren, subtrahieren und allen möglichen anderen Operationen mit deiner Klasse passieren soll.
Code: Alles auswählen
class a:
def __init__(self,arg1):
self.arg1=arg1
class b(a): #Ableiten von a
def __init__(self,ar1,arg2):
a.__init__(self,arg1) #hier wird self übergeben! --> der Konstruktor (init) von a wird an b (momentan self) gerufen
self.arg2=arg2
...
>>> x=b(1,2)
>>> b.arg1,b.arg2
(1 , 2)
Zuletzt geändert von Milan am Mittwoch 9. Juli 2003, 14:33, insgesamt 1-mal geändert.
Nein. Überladen heißt: Überschreiben. Und überschrieben wird eine Methode der Elternklasse, wenn ich in der Kindklasse eine gleichnamige Methode definiere. Damit wird, wenn ich die Methode einer Instanz der Kindklasse rufe, die Methode der Kindklasse genommen, und nicht mehr die der Elternklasse.rolgal hat geschrieben: das mit dem konstruktor habe ich hoffentlich verstanden: er wird nur dann überladen, wenn in der subklasse der konstruktor der elternklasse aufgerufen wird, oder?
Gerade bei Konstruktor-Methoden ist dieses Verhalten jedoch oft (aber nicht immer) unerwünscht. Wir wollen ja meistens, daß die Konstruktoren aller Klassen ausgeführt werden, da sie meistens irgendwelche wichtigen Initialisierungen durchführen.
Also müssen wir im Kindklassen-Konstruktor, der ja den Konstruktor der Elternklasse übercshrieben hat, den Konstruktor der Elternklasse explizit aufrufen, damit die dort enthaltenen Anweisungena auch wirklich ausgeführt werden.
Jörg
-
- Python-Forum Veteran
- Beiträge: 2010
- Registriert: Freitag 11. Oktober 2002, 18:00
- Wohnort: Salzburg
- Kontaktdaten:
Hallo Roland,
Beispiel:
A ist die Basisklasse.
Bei B wird der Konstruktor überladen da mehr Parameter verwendung finden und der Konstruktor der Basisklasse, mit den für diese notwendigen Parametern aufgerufen.
Bei C wird der Konstruktor der Basisklasse nicht überladen, daher er wird von A geerbt und beim instanziieren der Klasse ausgeführt!
Bei D wird der Konstuktor überladen, aber nicht der Konstruktor der Basisklasse A aufgerufen. Dies ist nicht zu empfehlen, da bei einer Änderung des Konstruktors der Basisklasse diese Änderung in D nicht bemerkt wird und so zu seltsamen Verhalten der Instanzen führen kann.
Also merke, wenn keine zusätzlichen Initialisierungen in der Kindklasse nötig sind, einfach den Konstruktor __init__ nicht überladen, sind zusätzliche Parameter und Initialisierungen nötig, so überlade den Konstruktor und führe an geeigneter Stelle den Konstruktor der Basisklasse aus.
Jede Basisklasse, also eine Klasse die nicht von einer anderen Klasse abgeleitet wird sollte, auch wenn (noch) keine Initialisierungen nötig sind einen __init__ Konstruktor definieren. So sind bei späteren Erweiterungen der Basisklasse keine Überaschungen bei von dieser abgeleiteten Kindklassen zu erwarten.
Gruß
Dookie
nein, umgekehrt, wenn der Kunstruktor also die Methode __init__ nicht überlagden wird, wird immer, falls vorhanden der Konstruktor der Elternklasse ausgeführt.rolgal hat geschrieben: das mit dem konstruktor habe ich hoffentlich verstanden: er wird nur dann überladen, wenn in der subklasse der konstruktor der elternklasse aufgerufen wird, oder?
Beispiel:
Code: Alles auswählen
class A:
def __init__(self, a): # Konstruktor für A
self.a = a
print "Der Konstruktor von A wurde ausgeführt!"
class B(A):
def __init__(self, a, b): # Konstruktor für B
A.__init__(self, a) # Konstruktor für A aufrufen
self.b = b
print "Der Konstruktor von B wurde ausgeführt!"
class C(A): # hier gibts keinen eigenen Konstruktor
def Hallo(self):
print self.a
class D(A):
def __init__(self, d): # Konstruktor für D
self.d = d
print "Der Konstruktor von D wurde ausgeführt!"
>>> a = A(1)
Der Konstruktor von A wurde ausgeführt!
>>> b = B(1,2)
Der Konstruktor von A wurde ausgeführt!
Der Konstruktor von B wurde ausgeführt!
>>> c = C(3)
Der Konstruktor von A wurde ausgeführt!
>>> d = D(4)
Der Konstruktor von D wurde ausgeführt!
>>>
Bei B wird der Konstruktor überladen da mehr Parameter verwendung finden und der Konstruktor der Basisklasse, mit den für diese notwendigen Parametern aufgerufen.
Bei C wird der Konstruktor der Basisklasse nicht überladen, daher er wird von A geerbt und beim instanziieren der Klasse ausgeführt!
Bei D wird der Konstuktor überladen, aber nicht der Konstruktor der Basisklasse A aufgerufen. Dies ist nicht zu empfehlen, da bei einer Änderung des Konstruktors der Basisklasse diese Änderung in D nicht bemerkt wird und so zu seltsamen Verhalten der Instanzen führen kann.
Also merke, wenn keine zusätzlichen Initialisierungen in der Kindklasse nötig sind, einfach den Konstruktor __init__ nicht überladen, sind zusätzliche Parameter und Initialisierungen nötig, so überlade den Konstruktor und führe an geeigneter Stelle den Konstruktor der Basisklasse aus.
Jede Basisklasse, also eine Klasse die nicht von einer anderen Klasse abgeleitet wird sollte, auch wenn (noch) keine Initialisierungen nötig sind einen __init__ Konstruktor definieren. So sind bei späteren Erweiterungen der Basisklasse keine Überaschungen bei von dieser abgeleiteten Kindklassen zu erwarten.
Gruß
Dookie
also, das scheint schon eine nicht ganz einfache sache zu sein. so wie oop allgemein. das prinzip ist ja relativ schnell klar, das aber effizient und sinnvoll anzuwenden scheint mir eine andere sache
wie meinte schon mal jmd. anderer zu dem thema an anderer stelle: ganz klar ist es noch nicht, aber es dämmert zumindest.
ich gehe das mal alles durch und erkläre es euch dann:-))))))))))))))))))))))
mfg
roland