__construct in Parent-Klasse automatisch aufrufen.
M.
- php
0 Tom2 Sven Rautenberg0 M.
Mahlzeit,
vermutlich überseh ich mal wieder irgendwas.
Ich erweitere eine Klasse und will, dass in der Parentklasse automatisch der Konstruktor aufgerufen wird.
Aktuell mach ich das per parent::__construct();
Ich will das aber ohne manuellen Aufruf. Gehen sollte das ja, das Laden der Klassendateien erfolgt per Autoloader. Wer hat ne schubs in die richtige Richtung für mich?
Hello,
vermutlich überseh ich mal wieder irgendwas.
Ich erweitere eine Klasse und will, dass in der Parentklasse automatisch der Konstruktor aufgerufen wird.
Aktuell mach ich das per parent::__construct();
einfach den ererbten Constructor nicht überschreiben!
" Note: Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required. If the child does not define a constructor then it may be inherited from the parent class just like a normal class method (if it was not declared as private). "
Dann kann man allerdings die Child-Class nicht mehr vernünftig initialisieren
Wird dir vermutlich nichts weiter übrig bleiben, als den Constructor der Parent-Class dediziert (im Constructor|in) der Child-Class aufzurufen.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Moin!
vermutlich überseh ich mal wieder irgendwas.
Ich erweitere eine Klasse und will, dass in der Parentklasse automatisch der Konstruktor aufgerufen wird.Aktuell mach ich das per parent::__construct();
Ich will das aber ohne manuellen Aufruf. Gehen sollte das ja, das Laden der Klassendateien erfolgt per Autoloader. Wer hat ne schubs in die richtige Richtung für mich?
Wenn du in deiner erbenden Klasse keinen Konstruktor definierst, musst du den der Parent-Klasse nicht explizit aufrufen.
Wenn du aber einen Konstruktor definierst, darf der Eltern-Konstruktor nicht automatisch aufgerufen werden. Wann sollte denn das geschehen? Vor oder nach dem eigenen Konstruktor-Code? Und mit welchen Parametern (die Parameterliste darf sich ja durchaus unterscheiden)? Und wie würde man den Aufruf des Parent-Konstruktors komplett verhindern? PHP kennt keinen "Nicht-Call".
- Sven Rautenberg
Hi,
Wenn du in deiner erbenden Klasse keinen Konstruktor definierst, musst du den der Parent-Klasse nicht explizit aufrufen.
Wenn du aber einen Konstruktor definierst, darf der Eltern-Konstruktor nicht automatisch aufgerufen werden. Wann sollte denn das geschehen? Vor oder nach dem eigenen Konstruktor-Code? Und mit welchen Parametern (die Parameterliste darf sich ja durchaus unterscheiden)? Und wie würde man den Aufruf des Parent-Konstruktors komplett verhindern? PHP kennt keinen "Nicht-Call".
Naja.
Bei Java ist das so gelöst:
Wenn der Constructor nicht als erstes einen Constructor der Super-Klasse aufruft, wird deren parameterloser Constructor aufgerufen. *)
Die PHP-Vorgehensweise kommt mir sehr seltsam vor.
Welchen Sinn soll es haben, daß *kein* Constructor der Super-Klasse aufgerufen wird? Das führt ggf. dazu, daß die Super-Klasse nicht initialisiert ist.
*) wenn in Java kein passender Constructor in der Super-Klasse existiert **): Compiler-Fehler.
**) wenn in einer Klasse gar kein Constructor definiert ist, ist in Java impliziert der parameterlose Constructor definiert, der (neben der Erzeugung des Objekts) nichts tut.
cu,
Andreas
Tach!
Die PHP-Vorgehensweise kommt mir sehr seltsam vor.
Welchen Sinn soll es haben, daß *kein* Constructor der Super-Klasse aufgerufen wird? Das führt ggf. dazu, daß die Super-Klasse nicht initialisiert ist.
Definiere "(nicht) initialisiert"! Der Konstruktor ist lediglich eine Funktion, die nach der Erzeugung des Objekts aufgerufen wird. Wenn es nichts weiter zu tun gibt, muss kein Konstruktor aufgerufen werden. Die Eigenschaften des Objekts können uninitialisiert (auf null) bleiben oder auch gleich bei ihrer eigenen Deklaration einen Wert zugewiesen bekommen, solange das ein konstanter Ausdruck ist. Und ob eine Elternklasse eine Initialisierung braucht oder nicht, kann man nicht mit einer verallgemeinernden Sinnfrage klären.
Anders gefragt, welchen Sinn sollte es haben, dass unter allen Umständen ein Konstruktor aufgerufen wird, selbst wenn der keine Funktion ausführt? Das wäre nur ein unnützer Funktionsaufruf - oder eine ganze Kette davon. Es mag da sicher Argumente in die eine und die andere Richtung geben, aber die Sinnfrage zu diskutieren ist müßig. PHP macht das auf eine bestimmte Art und Weise, die kann man beschreiben, damit man damit umgehen kann. Ob man das sinnvoll findet oder nicht, nützt beim Anwenden nicht weiter.
dedlfix.
Hello,
Anders gefragt, welchen Sinn sollte es haben, dass unter allen Umständen ein Konstruktor aufgerufen wird, selbst wenn der keine Funktion ausführt?
Noch anders gefragt: Was geht die Child-Klasse an, ob der Konstruktor der Parent-Klasse einen Sinn hat?
Da OOP ja wohl bei Vererbung nur deduktiv arbeitet, muss die Child-Class den Parent-Konstruktor auf jeden Fall aufrufen! Sie weiß ja nicht, was der macht ;-O
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Tach!
Da OOP ja wohl bei Vererbung nur deduktiv arbeitet, muss die Child-Class den Parent-Konstruktor auf jeden Fall aufrufen! Sie weiß ja nicht, was der macht ;-O
Also ich lese Dokumentationen und weiß dann, ob ich das Verhalten des Elternkonstruktors haben möchte oder nicht. (Für Verhaltensänderungen in späteren Versionen gibt es Changelogs und auch Test Driven Design.)
dedlfix.
Hello,
Da OOP ja wohl bei Vererbung nur deduktiv arbeitet, muss die Child-Class den Parent-Konstruktor auf jeden Fall aufrufen! Sie weiß ja nicht, was der macht ;-O
Also ich lese Dokumentationen und weiß dann, ob ich das Verhalten des Elternkonstruktors haben möchte oder nicht. (Für Verhaltensänderungen in späteren Versionen gibt es Changelogs und auch Test Driven Design.)
Das ist aber nicht der Sinn der OOP und der Vererbung, dass Kinder nahezu frei entscheiden, was in den Elternobjekten passiert. Dass der Konstruktor des Parent nicht sofort bei der Instantiierung über das Child aufgerufen wird, ist schon ein Risiko für die Stabilität.
Ich teile da die Meinung der Java-Entwickler. Wenn im Konstruktor des Childs der Parent-Construktor nicht mit Attributen aufgerufen wird, wird er eben automatisch ohne Parameter aufgerufen!
Wenn die Elternklasse Abweichungen von der bei der Instanttiierung möglichen Initilisierung wünscht, muss sie eben Methoden dafür bereitstellen.
Alles andere ist Schmuddelprogrammierung!
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Meine Herren!
Ich teile da die Meinung der Java-Entwickler. Wenn im Konstruktor des Childs der Parent-Construktor nicht mit Attributen aufgerufen wird, wird er eben automatisch ohne Parameter aufgerufen!
Ich befürworte da sehr stark JavaScripts Lösung, dass die Objekt-Erzeugung (Constructor, Factory, Literale usw.) von der Vererbung (Prototypen) getrennt sein sollte. Darauf aufbauend sind wunderbare, zu tiefst verschiedene Projekte entstanden: stampit vs proto
Alles andere ist Schmuddelprogrammierung!
Pfui! Bleib sachlich, Sportsfreund ;)
Hi,
Definiere "(nicht) initialisiert"! Der Konstruktor ist lediglich eine Funktion, die nach der Erzeugung des Objekts aufgerufen wird.
Ist das in PHP so? In Java ist der Konstruktor eine Funktion, die das Objekt erzeugt (und ggf. noch mehr tut).
Anders gefragt, welchen Sinn sollte es haben, dass unter allen Umständen ein Konstruktor aufgerufen wird, selbst wenn der keine Funktion ausführt?
Aufgabe des Konstruktors ist üblicherweise (C++, Java, ...), das Objekt zu erzeugen.
Bei der PHP-Variante muß dann wohl die ableitende Klasse Implementierungsdetails der Super-Klasse kennen (z.B. ob es nötig ist, eine bestimmte Konstruktor-Methode aufzurufen).
Das widerspricht m.E. den OOP-Prinzipien (Encapsulation, Information Hiding).
cu,
Andreas
Tach!
Definiere "(nicht) initialisiert"! Der Konstruktor ist lediglich eine Funktion, die nach der Erzeugung des Objekts aufgerufen wird.
Ist das in PHP so? In Java ist der Konstruktor eine Funktion, die das Objekt erzeugt (und ggf. noch mehr tut).
Das ist ein Henne-und-Ei-Problem. Wenn der Konstruktor Teil des Objekts ist, wie kann er dann aufgerufen werden, um das Objekt zu erzeugen, wenn das Objekt noch gar nicht da ist? Das grundlegende Erzeugen eines Objektes (Reservieren von Speicher und so weiter) muss vorher passieren - das kann der new-Operator erledigen. Der Konstruktor ist dann eine spezielle Funktion, die beim Initialisierungsprozess aufgrufen wird, die zum Initialisieren der Werte in den Eigenschaften dient - so man das möchte.
Bei der PHP-Variante muß dann wohl die ableitende Klasse Implementierungsdetails der Super-Klasse kennen (z.B. ob es nötig ist, eine bestimmte Konstruktor-Methode aufzurufen).
Es gibt keine Methodenüberlagerung in PHP. Es gibt genau einen Konstruktor oder keinen. (Allerdings kommt hier eine historisch bedingte Besonderheit ins Spiel, als die Konstruktor-Funktion noch nicht __construct hieß sondern wie der Namen der Klasse. Das will ich aber nicht näher ausführen und tut auch nichts grundlegendes zur Sache.) In einer abgeleiteten Klasse jedenfalls ruft man den Elternkonstruktor auf, oder lässt es bleiben.
dedlfix.
hi,
Definiere "(nicht) initialisiert"! Der Konstruktor ist lediglich eine Funktion, die nach der Erzeugung des Objekts aufgerufen wird.
Ist das in PHP so? In Java ist der Konstruktor eine Funktion, die das Objekt erzeugt (und ggf. noch mehr tut).
Anders gefragt, welchen Sinn sollte es haben, dass unter allen Umständen ein Konstruktor aufgerufen wird, selbst wenn der keine Funktion ausführt?
Aufgabe des Konstruktors ist üblicherweise (C++, Java, ...), das Objekt zu erzeugen.
Bei der PHP-Variante muß dann wohl die ableitende Klasse Implementierungsdetails der Super-Klasse kennen (z.B. ob es nötig ist, eine bestimmte Konstruktor-Methode aufzurufen).
Das widerspricht m.E. den OOP-Prinzipien (Encapsulation, Information Hiding).
Ich erbe doch von einer Klasse, um sie meinen Bedürfnissen ggfs. anzupassen. Da _muss_ ich doch wissen, was ich von der Elternklasse haben will. Auch hier nochmal der Link zu eine Beispiel aus dem Zend-Framework: http://stackoverflow.com/questions/3334938/zend-framework-extend-zend-form-to-add-default-form-elements
mfg
tami
Hi,
Ich erbe doch von einer Klasse, um sie meinen Bedürfnissen ggfs. anzupassen.
Das öffentliche Interface muß bekannt sein.
Aber nicht die Implementierungsdetails.
Es geht z.B. niemanden außerhalb der Klasse etwas an, in welcher Datenstruktur eine Klasse ihre internen Daten hält.
Es reicht, die öffentlichen Zugriffs- und Manipulations-Methoden zu kennen.
cu,
Andreas
Hi,
Ich erbe doch von einer Klasse, um sie meinen Bedürfnissen ggfs. anzupassen.
Das öffentliche Interface muß bekannt sein.
Aber nicht die Implementierungsdetails.Es geht z.B. niemanden außerhalb der Klasse etwas an, in welcher Datenstruktur eine Klasse ihre internen Daten hält.
Es reicht, die öffentlichen Zugriffs- und Manipulations-Methoden zu kennen.
Na und? Der Konstruktor, inklusive seiner Parameter, ist doch öffentlich – also wo ist das Problem?
MfG ChrisB
Hello,
Na und? Der Konstruktor, inklusive seiner Parameter, ist doch öffentlich – also wo ist das Problem?
Das Problem liegt mMn nur in der eigenwilligen Art von PHP, das das Nichtaufrufen des Parent-Constructor als Default einstellt, wenn man in der Childclass einen eigenen deklariert.
Ich wiederhole nochmals meine Meinung: ich hielte es für besser, dass der Eltern-Konstruktor auf jeden Fall aufgerufen wird bevor der Kind-Konstruktor aktiv wird, notfalls automatisch und dann eben mit den voreingestellten Attributen.
Java bekommt das hin. Wieso sollte PHP das nicht auch schaffen?
Wenn ich mich recht erinnere, muss der Aufruf in Java sogar als erste Anweisung des Child Contructors stattfinden, sonst wird der Konstruktor der Parent-Class automatisch mit den Voreinstellungen aufgerufen.
Bitte korrigiere mich, wenn das nicht stimmt.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Mahlzeit,
Ich wiederhole nochmals meine Meinung: ich hielte es für besser, dass der Eltern-Konstruktor auf jeden Fall aufgerufen wird bevor der Kind-Konstruktor aktiv wird, notfalls automatisch und dann eben mit den voreingestellten Attributen.
Ja, das würde IMO auch Sinn machen. Ein Parent wird ja instanziert, da sonst das Objekt gar nicht existiert. Und sobald es instanziert wird, sollte der Konstruktor aufgerufen werden.
Java bekommt das hin. Wieso sollte PHP das nicht auch schaffen?
Da gibts es wirklich was, was Java für mich sympathisch macht? ;)
Hello,
Ich erbe doch von einer Klasse, um sie meinen Bedürfnissen ggfs. anzupassen.
Du sollst die Klasse anpassen, nicht aber das Paradigma der OOP.
Nun meine ich, dass der Constructor zum Paradigma der OOP gehört und daher nicht "wegdiskutiert" oder "weg-angepasst" werden darf.
Wenn die Eingriffe in einer Elternklasse an Stellen stattfinden, an denen sie eigentlich nicht geplant waren, sollte man besser die ganze Klasse neu erstellen. Da ist dann aber von "Weiterverwendung von Code" nicht mehr die Rede.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
hi,
Hello,
Ich erbe doch von einer Klasse, um sie meinen Bedürfnissen ggfs. anzupassen.
Du sollst die Klasse anpassen, nicht aber das Paradigma der OOP.
Nun meine ich, dass der Constructor zum Paradigma der OOP gehört und daher nicht "wegdiskutiert" oder "weg-angepasst" werden darf.Wenn die Eingriffe in einer Elternklasse an Stellen stattfinden, an denen sie eigentlich nicht geplant waren, sollte man besser die ganze Klasse neu erstellen. Da ist dann aber von "Weiterverwendung von Code" nicht mehr die Rede.
http://php.net/manual/de/keyword.extends.php
und
https://forum.selfhtml.org/?t=216772&m=1487402
Es ist in PHP einfach Fakt und macht die entsprechenden Anpassungen möglich. Mag sein, dass es nicht in eine bestimmte Definition von OOP passt. Das ist aber glaube ich auch nicht Anliegen der Sprache. PHP is not Java ;-). Und kann mittlerweile sogar Closures.
mfg
tami
Meine Herren!
Wenn die Eingriffe in einer Elternklasse an Stellen stattfinden, an denen sie eigentlich nicht geplant waren, sollte man besser die ganze Klasse neu erstellen.
ACK. Vererbung ist sowieso eine sehr starke Form der Assoziation, die man oft nicht haben möchte, und am wenigsten über Paket-Grenzen hinaus. Ich erinnere mich da an eine Typo3-Erweiterung, die ich mal implementieren musste, die a) PDFs mit einem Wasserzeichen versieht und b) den Schreibzugriff darauf sperrt. Für die Auslieferung der PDF-Dateien war bereits eine Erweiterung im Einsatz und es waren auch schnell zwei Erweiterungen gefunden, die darauf aufbauend a) und b) gelöst haben – ABER beide Lösungen haben unnötiger Weise von der selben Basis-Klasse geerbt und waren deshalb nur sehr schwierig zusammen zu führen. Ich habe damals die fast fertigen Lösungen umgestrickt und die Vererbung aufgelöst.
Always prefer composition over inheritance.
~ GOF
Moin!
Ich erbe doch von einer Klasse, um sie meinen Bedürfnissen ggfs. anzupassen. Da _muss_ ich doch wissen, was ich von der Elternklasse haben will. Auch hier nochmal der Link zu eine Beispiel aus dem Zend-Framework: http://stackoverflow.com/questions/3334938/zend-framework-extend-zend-form-to-add-default-form-elements
Das ist eher ein schlechtes Beispiel, weil es auf Zend Framework 1 basiert, und deshalb zwangsläufig die etwas reduzierteren OOP-Möglichkeiten von frühen PHP5-Versionen kombiniert mit einem noch nicht ganz so fortgeschrittenen Verständnis von OOP generell.
- Sven Rautenberg
Moin!
Naja.
Bei Java ist das so gelöst:
Wenn der Constructor nicht als erstes einen Constructor der Super-Klasse aufruft, wird deren parameterloser Constructor aufgerufen. *)
Bei PHP ist der Konstruktor nicht dafür verantwortlich, die Instanz des Objektes zu erzeugen, sondern er wird (optional) zusätzlich NACH Erzeugung der Instanz aufgerufen. Wobei anzumerken ist: Wenn man innerhalb des Konstruktors eine Exception wirft, erhält man kein Objekt.
Die PHP-Vorgehensweise kommt mir sehr seltsam vor.
Sie ist nur genau aufgrund der oben genannten Tatsache sinnvoll: Objekte in PHP werden immer "konstruktorlos" konstruiert, wenn man keine expliziten Konstruktorfunktionen angibt.
Welchen Sinn soll es haben, daß *kein* Constructor der Super-Klasse aufgerufen wird? Das führt ggf. dazu, daß die Super-Klasse nicht initialisiert ist.
Klassen lassen sich in PHP auch ohne Konstruktor initialisieren (sofern wir beide dasselbe damit meinen): Konstante Werte lassen sich z.B. den Members der Klasse im Code zuweisen.
- Sven Rautenberg
Mahlzeit,
erstmal danke an alle, wieder was gelernt :)
Mal sehen, wie ich es umsetze. Zumindest muss die Doku dann hergeben, dass diverse Variablen und Methoden erst nach Aufruf des Konstruktors zur Verfügung stehen.
hi,
Mahlzeit,
erstmal danke an alle, wieder was gelernt :)
Mal sehen, wie ich es umsetze. Zumindest muss die Doku dann hergeben, dass diverse Variablen und Methoden erst nach Aufruf des Konstruktors zur Verfügung stehen.
Aber wenn das keine statische Klasse ist, wird der Konstruktor doch sowieso immer aufgerufen, wenn du ein Objekt initialisierst ... ???
Vielleicht hilft Dir ja sowas (http://stackoverflow.com/questions/3334938/zend-framework-extend-zend-form-to-add-default-form-elements) noch weiter?
mfg
tami
Mahlzeit,
Aber wenn das keine statische Klasse ist, wird der Konstruktor doch sowieso immer aufgerufen, wenn du ein Objekt initialisierst ... ???
Ich initialisiere ja nur das Kind-Objekt, das die Eltern-Klasse erweitert. Offensichtlich wird dabei der Parent-Konstruktor nicht aufgerufen.
Vielleicht hilft Dir ja sowas (http://stackoverflow.com/questions/3334938/zend-framework-extend-zend-form-to-add-default-form-elements) noch weiter?
Schau ich mir an, danke.
hi,
Mahlzeit,
Aber wenn das keine statische Klasse ist, wird der Konstruktor doch sowieso immer aufgerufen, wenn du ein Objekt initialisierst ... ???
Ich initialisiere ja nur das Kind-Objekt, das die Eltern-Klasse erweitert. Offensichtlich wird dabei der Parent-Konstruktor nicht aufgerufen.
Nein, natürlich nicht. Das willst Du doch selbst entscheiden. Im Zend-Framework kannst Du somit Klassen beerben und dann selbst entscheiden, ob Du den Parent-Konstruktor nutzen willst oder ihn überschreiben möchtest. Wenn dort die Funktion init() aufgerufen wird, kannst Du auch init() definieren und im Konstruktor Deiner ("Kind-")Klasse parent::__construct() aufrufen. Andernfalls ließe sich ja auch der Elternkonstruktor nicht (bei Bedarf) "abschalten".
http://php.net/manual/de/keyword.extends.php beschreibt das ja auch nochmal.
mfg
tami