M.: __construct in Parent-Klasse automatisch aufrufen.

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?

--
42
  1. 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

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bikers-lodge.com
  2. 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

    1. 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

      --
      Warum nennt sich Andreas hier MudGuard?
      O o ostern ...
      Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
      1. 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.

        1. 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

          --
           ☻_
          /▌
          / \ Nur selber lernen macht schlau
          http://bikers-lodge.com
          1. 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.

            1. 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

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bikers-lodge.com
              1. 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 ;)

                --
                “All right, then, I'll go to hell.” – Huck Finn
        2. 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

          --
          Warum nennt sich Andreas hier MudGuard?
          O o ostern ...
          Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
          1. 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.

          2. 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

            1. 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

              --
              Warum nennt sich Andreas hier MudGuard?
              O o ostern ...
              Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
              1. 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

                --
                Autocomplete has spoiled me to a point where it happens every so often that I encounter a CAPTCHA, and I just type in the first character … and then wait for the rest of the code to be automatically suggested :/
                1. 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

                  --
                   ☻_
                  /▌
                  / \ Nur selber lernen macht schlau
                  http://bikers-lodge.com
                  1. 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? ;)

                    --
                    42
            2. 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

              --
               ☻_
              /▌
              / \ Nur selber lernen macht schlau
              http://bikers-lodge.com
              1. 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

              2. 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

                --
                “All right, then, I'll go to hell.” – Huck Finn
            3. 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

      2. 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

  3. 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.

    --
    42
    1. 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

      1. 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.

        --
        42
        1. 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