Warum ruft PHP nicht automatisch übergeordnete Konstruktoren auf?

Lesezeit: 7 Minuten

Benutzer-Avatar
Geschicklichkeit

Ziemlich einfache Frage. In C++ wird der übergeordnete Konstruktor implizit vor dem untergeordneten Konstruktor aufgerufen. Welche Logik gibt es also für PHP, um Dinge nicht auf diese Weise zu tun?

BEARBEITEN: Ich habe eine gute Antwort von Lukman bekommen, aber ich hatte auf mehr Gründe gehofft, warum es einen Unterschied gibt. Vielleicht sollte die Frage lauten, warum C++ keine benutzerdefinierten Aufrufe von übergeordneten Konstruktoren zulässt? Ich denke, das ist aber eine andere Frage.

  • Ja ich verstehe das! Ich bin mir sicher, dass es Unterschiede in den Sprachen gibt, die die Entscheidung beeinflusst haben, die Eltern anzurufen oder nicht anzurufen – ich möchte die Gründe wissen.

    – Geschicklichkeitsdrick

    15. Dezember 2009 um 10:28 Uhr

  • Das ist ein bisschen so, als würde man sagen “Warum quaken Hunde nicht?”: “Weil sie keine Enten sind.”

    – Geschicklichkeitsdrick

    15. Dezember 2009 um 10:30 Uhr

  • 2Skilldrick: sieht so aus, als wäre dies die Antwort auf die Frage 🙂

    – Nikita Fedyashev

    15. Dezember 2009 um 11:15 Uhr

  • Weil es eine schreckliche Sprache ist, die vermieden werden sollte. PHP ist ein Fraktal schlechten Designs. – eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design . C++ “erlaubt es Ihnen irgendwie”, indem es den ctor mit einem leeren überlädt und stattdessen durch diese Signatur erbt. Ein Konstruktor sollte tun, was auf der Dose steht, er sollte aufgerufen werden, wenn das Objekt konstruiert ist, und sollte das Objekt konstruieren, wenn er dies nicht tut, vergisst er seinen Zweck. PHP ist voller Macken wie dieser und hat einfach wirklich keinen guten Grund dahinter, im Ernst. Benötigen Sie Hilfe beim Erlernen von C#, fragen Sie einfach.

    – Jimmyt1988

    31. Juli 2016 um 1:57 Uhr

Benutzer-Avatar
Lukas

Ich denke, es ist eine gute Sache, dass PHP Sie dazu bringt, den Konstruktor des übergeordneten Elements manuell aufzurufen, da es den Konstruktor des untergeordneten Elements wie folgt zulässt:

public function __construct() {
   // set up variables that parent::__construct() requires
   $var1 = get_stuff_from_db();
   $var2 = get_stuff_from_webservice();

   parent::__construct($var1, $var2);

   // continue setting up $this var
   $this->default="Default";
   $this->do_some_secret_stuff();
}

Oder auch:

public function __construct($param) {
   // call differently based on condition
   if (is_array($param))
      $param['id'] = 0;
      parent::__construct($param);
   }
   else {
      parent::__construct($param, 0, TRUE);
   }

   // continue setting up $this var
   $this->default="Default";
   $this->do_some_secret_stuff();
}

Das heißt, Sie können den übergeordneten Konstruktor überall innerhalb des untergeordneten Konstruktors aufrufen und vor und nach dem Aufruf frei Dinge tun. Ist das nicht tatsächlich ein Feature?

  • Beachten Sie, dass Sie den übergeordneten Konstruktor problemlos nur dann automatisch aufrufen können, wenn der Konstruktorkörper nicht bereits einen expliziten Aufruf enthält.

    – putgeminmouth

    6. Januar 2011 um 7:37 Uhr

  • Eine Basisklasse, die eine Initialisierung einer untergeordneten Klasse erfordert, bevor sie sich selbst initialisieren kann … :O Ich würde jedem in diesem Szenario dringend empfehlen, sein Anwendungsdesign zu überdenken. Andererseits gibt es mit PHP keine Grenzen für den potenziellen Kludge-Faktor.

    – Entwicklerbmw

    15. Juni 2015 um 22:05 Uhr


  • Das ist schlecht, weil der Konstruktor immer aufgerufen werden sollte, wenn ein Objekt instanziiert wird. Durch den Vererbungszyklus wird der geerbte Objekttyp instanziiert und hat dennoch ein Flag, das angibt, dass der Konstruktor nicht ausgelöst werden soll. Dies verstößt gegen die allgemeine Konstruktorregel und führt zu Verwirrung (Beweis befindet sich im OP). Andererseits erlauben Sprachen wie C# oder C++ eine verzögerte Ausführung von Konstruktoren, indem sie implizit danach fragen, anstatt gegen die Standardregel zu verstoßen, dass Konstruktoren bei der Instanziierung aufgerufen werden. Dies ist ein wirklich dummer Teil von PHP und sollte behoben werden.

    – Jimmyt1988

    28. Juli 2016 um 17:24 Uhr

  • @developerbmw – Denken Sie noch einmal nach. Warum sollten Sie eine Funktion erstellen, um “erforderliche Objekte zu instanziieren”, wenn Ihnen ein Konstruktor für genau diese Aufgabe zur Verfügung gestellt wird? Tatsächlich heißt es sogar in der PHP-Dokumentation: “Es ist für jede Initialisierung geeignet, die das Objekt möglicherweise benötigt, bevor es verwendet wird.”. Bitte machen Sie keine Empfehlungen an andere, da Sie sie möglicherweise falsch anleiten. Dies ist ein grundlegendes Versehen von PHP und für Neulinge in der Sprache verwirrend. Es sollte aufgelöst und als Konfiguration für PHP festgelegt werden, damit Legacy-Code nicht beschädigt wird.

    – Jimmyt1988

    28. Juli 2016 um 17:30 Uhr


  • @developerbmw: Vielleicht vergessen Sie, dass es zwei Arten der Vererbung gibt; Generalisierung und Spezialisierung. Wenn Sie eine übergeordnete Klasse mit einer untergeordneten Klasse erweitern, handelt es sich um eine Spezialisierung, die den Konstruktor der untergeordneten Klasse nicht dazu veranlasst, den Konstruktor der übergeordneten Klasse explizit aufzurufen. Wenn Sie jedoch die Generalisierung implementieren (allgemeine Funktionalität in der Basisklasse ausklammern), kann dies ein gültiger Anwendungsfall sein. Zweitens wird in ORMs das Entitätsobjekt hydratisiert, ohne den Konstruktor aufzurufen. Ich sehe Weisheit in der Flexibilität, die PHP seinen Programmierern bietet.

    – Fakhar Anwar

    30. Dezember 2017 um 18:21 Uhr

Benutzer-Avatar
Programmhammer

Wenn Sie keinen Konstruktor in der untergeordneten Klasse haben, wird automatisch der übergeordnete Konstruktor aufgerufen.

Wenn Sie sich entschieden haben, der untergeordneten Klasse einen Konstruktor hinzuzufügen, müssen Sie den übergeordneten Konstruktor natürlich explizit aufrufen. Wenn Sie sich bereits die Zeit nehmen, Ihrer untergeordneten Klasse einen Konstruktor hinzuzufügen, fügen Sie eine weitere Codezeile hinzu parent::__construct(); scheint keine große Sache zu sein. Aber das Überschreiben ist eigentlich eine bequeme Flexibilität.

  • PHP ist die einzige Sprache, die schlechtes Design als “eine bequeme Flexibilität” bezeichnen kann 😀

    – Entwicklerbmw

    15. Juni 2015 um 22:07 Uhr

  • Nicht sicher, was Sie hier sagen? Ich denke, es ist tatsächlich ein besseres Design, nur einen Konstruktor zu haben, der dafür verantwortlich ist, das Objekt in einen gültigen Zustand zu bringen. Durch das Mischen zwischen untergeordnetem und übergeordnetem Konstruktor würde ich sagen, dass es mehr zu beachten gibt. Andernfalls erstellen Sie einfach keinen untergeordneten Konstruktor. Daher fördert PHP praktischerweise die Verwendung eines einzigen Konstruktors.

    – Programmhammer

    16. Juni 2015 um 15:24 Uhr


  • @Brett, von welcher Art von schlechtem Design redest du; erklären?

    – Kyslik

    3. September 2015 um 11:15 Uhr

  • @Kyslik, den übergeordneten Konstruktor explizit aufrufen zu müssen, könnte zu Problemen führen, wenn er vergessen wird. Sie könnten argumentieren, dass es hilfreich sein könnte, den Aufruf des übergeordneten Konstruktors wegzulassen, aber in diesem Fall sollten Sie Ihr Klassendesign überdenken.

    – Entwicklerbmw

    4. September 2015 um 4:46 Uhr

  • In diesem Fall können Sie eine Art “neue Ausnahme werfen: hey Konstruktor wurde nicht aufgerufen” (oder etwas Ähnliches in der übergeordneten Klasse) und das Problem ist gelöst … Ich möchte mein Code DRY sein, daher verwende ich abstrakte Eltern und Arbeit mit Kindern nur, wenn es Sinn macht.

    – Kyslik

    7. September 2015 um 8:30 Uhr

Um eine enge Kopplung zu vermeiden, ist die Vererbung (Schlüsselwort erweitern in Java) böse und die Schnittstellenklasse wird bevorzugt, siehe Javaworld-Artikel:
http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html

Trotzdem wäre es großartig, wenn es eine Anweisung geben würde, die Eltern irgendwann mit einem speziellen Schlüsselwort wie forward anzurufen, aber ich habe dies noch in keiner Sprache (sogar Rebol) gesehen, außer in einer unbekannten Sprache, die von Paul Allen erfunden wurde (ja, die Co -Gründer von Microsoft), das Openscript ist.

  • Elternmethode aufrufen? viele OOP-Sprachen haben das. Wie parent Präfix in PHP, super() in Python, super in Java und sogar mit dem Namen der übergeordneten Klasse wie BaseClass::method() in C++.

    – Lukmann

    21. Dezember 2009 um 16:01 Uhr

  • ALLE OOP haben, dass das ein Teil von OOP ist :). Das bedeutet nicht, dass Sie es überbeanspruchen sollten.

    – Rebol-Tutorial

    25. Dezember 2009 um 19:49 Uhr

  • Erbschaft ist böse? Was? Sie sagen also, dass die bloße Tatsache, dass eine Schlange und eine Giraffe Tiere sind, Sie keine Attribute einer Tierklasse erben sollten, sondern eher … was? eine Schnittstelle erstellen, die eine Methode hat, die Zeiger auf ein Tier bezeichnet? Was? Wie ist das überhaupt richtig? Meine Güte. Und bringen Sie mich nicht zu Leuten, die sagen: “Mehrfachvererbung sollte nicht existieren”, es gibt Fälle aus dem wirklichen Leben, in denen dies logisch sinnvoll ist. Es sind seltene Fälle, aber es gibt sie.

    – Jimmyt1988

    31. Juli 2016 um 1:34 Uhr

  • @ Jimmyt1988 Für den besonderen Fall von Tieren ist es vollkommen gültig, Vererbung zu verwenden. Beim Codieren realer Anwendungen ist es jedoch nicht üblich, diese Art von Domänenobjekten zu haben. In diesen Szenarien sagen Entwickler oft: “Ich werde diese Klasse erweitern, damit ich diese Logik nicht erneut implementieren muss”. Das nutzt die Vererbung auf eine Weise aus, die nicht verwendet werden soll

    – Fermin Silva

    18. Oktober 2016 um 15:45 Uhr


  • @Fermin Silva – du sagst also, wenn du ein Spiel über Tiere oder außerirdische Arten oder Schiffe oder andere Objekte außerhalb dieser Welt machst, findest du es nicht nützlich oder nicht einmal … sinnvoll? Was ist mit Materialien wie Titan und Legierungen, die Sie nicht von Metall erben möchten? oder Bekleidung wie Hose und Rock möchte nicht von Bekleidung erben? Das ist, was es für Kumpel ist, und es kommt in fast jedem Programm / Spiel vor, das ich schreibe. Sehen Sie den Unterschied, ein Auto erbt nicht vom Motor, es macht keinen Sinn. Es enthält eine Engine, das ist, wenn Sie Zeiger haben.

    – Jimmyt1988

    19. Oktober 2016 um 8:27 Uhr

1159110cookie-checkWarum ruft PHP nicht automatisch übergeordnete Konstruktoren auf?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy