2015-10-04 7 views
6

Ich habe ein generelles Problem mit diesem Anwendungsfall: Ich habe eine Klasse A. Diese Klasse hat eine nicht abstrakte Methode doStuffCallback(), die überschrieben werden könnte, aber es ist nicht für jede Unterklasse erforderlich. Aber: Ich möchte sicherstellen, dass, wenn die Methode überschrieben wird, die Unterklasse-Methode die Eltern-Methode aufrufen muss.OOP (PHP) - Force überschrieben Methode zum Aufruf der entsprechenden Eltern-Methode

Beispiel:

abstract class A { 
    private function doStuff() { 
     $this->doStuffCallback(); 
    } 

    protected function doStuffCallback() { 
     // IMPORTANT CODE HERE 
    } 
} 

class B extends A { 
    protected function doStuffCallback() { 
     parent::doStuffCallback(); // I want to enforce this because the parents method code is important 

     // ALSO IMPORTANT CODE 
    } 
} 

Da die überschriebene Methode die gleiche Sache tut es sehr hässlich sein würde zwei Methoden für die gleiche Verantwortung und eine private Helfer-Methode, die beiden Anrufe zu definieren. Gefällt mir:

abstract class A { 
    private function doStuff() { 
     $this->callDoStuffCallback(); 
    } 

    private function callDoStuffCallback() { 
     $this->internalDoStuffCallback(); 
     $this->doStuffCallback(); 

     // This is VERY ugly 
    } 

    private function internalDoStuffCallback() { 
     // IMPORTANT CODE HERE 
    } 

    protected function doStuffCallback() {} 
} 

class B extends A { 
    protected function doStuffCallback() { 
     // IMPORTANT CODE 
    } 
} 

Das ist wirklich hässlich und mühsam. Also meine Frage: Gibt es einen Weg in PHP, um überschriebene Methoden zum Aufruf der Eltern-Methode zu erzwingen?

Antwort

6

Nein, es gibt keine solche Sprache-Funktion in PHP; Diese Einschränkung ist in den meisten Subtyp-'OO'-Sprachen nicht möglich.

Stattdessen müssen Programme auf expliziten Dokumentationsverträgen beruhen; und hoffentlich Einheitstests, um die Konformität sicherzustellen.


Guards auch so eingesetzt werden, dass irgendwann nach und nach, wenn ein Verfahren auf der übergeordneten Klasse verwendet wird, könnte es eine Ausnahme auslösen, wenn der ‚aktuelle Zustand‘ nicht gültig ist (z. B. solche und Solch eine Methode wurde noch nicht aufgerufen). Dies kann auch expliziter gemacht werden, indem die Unterklasse, die (wie in dem Dokumentationsvertrag definiert) erforderlich ist, eine spezielle Methode anstatt nur die überschriebene Supermethode aufruft. Dies liegt jedoch außerhalb eines beliebigen Systemtyps.

Während die self:: Umfang konnte verwendet werden (. ZB Aufruf nicht überschriebene Methode, die überschriebene Methode aufruft), das weitere Magie verbunden wäre eine unendliche Rekursion Schleifen zu vermeiden (zB einige Stapel Zustand.); und es wäre so einfach, die Verwendung versehentlich auszulassen.

Meine Empfehlung ist, eine (private) Methode aufzurufen, die diese 'vielleicht überschriebene' Methode in Beziehung zu welcher Logik auch immer anwendet, wie im Beispiel gezeigt (obwohl hoffentlich mit mehr Aufgaben spezifischen Tames). Dann wird die (geschützte) überschriebene Methode nicht erwartet oder benötigt, um irgendeine der speziellen Logik selbst zu behandeln; es soll auch nicht direkt außerhalb des durch die Elternklasse festgelegten Kontexts aufgerufen werden - es ist genau das, was es derzeit zu sein vorgibt, ein spezieller Rückruf.

+0

Danke für Ihre Antwort! Ich denke genau dasselbe. Ich glaube, dass die OOP, die wir heute benutzen, noch nicht vollständig ist. Es gibt so viele Aspekte, die wichtig sind, aber nicht behandelt werden. –

-2

Nein, können Sie zugreifen, können Sie die Methode für Eltern verwenden, wie diese

<?php 

class A { 

    function s1($p1) { 
     echo 's1: '.$p1; 
    } 
} 


class B extends A { 

    public function callParent($method, $p1) { 
     parent::$method($p1); 
    } 
} 


$b = new B(); 

$b->callParent('s1', 'param1'); 

oder ersetzen auf magische Methoden erstreckt __call usw. https://github.com/StagnantIce/php_extend_magic/blob/master/AExtendClass.php

+0

Wie löst das mein Problem? Ich denke, das ist eine weniger intelligente Lösung als nur zu erwarten, dass die Unterklasse die richtige Implementierung mit Dokumentation durchführt (rufen Sie die Elternmethode beim Überschreiben auf). Ich meine, Ihre Beispiele verlangen, dass JEDER CLIENT der Klasse und nicht nur die implementierte Klasse die Elternmethode reflexionsartig aufrufen muss. Dies ist der kontraintuitivste und unsicherste Ansatz, den ich je gesehen habe. Nichts für ungut :) –

2

Ich stimme eher mit "Das ist sehr hässlich". Es ist die Standardmethode, um diesen Anwendungsfall und eine Variante der Template Method Pattern zu behandeln.

Jetzt rate ich nur, weil Sie kein reales Beispiel angegeben haben, aber wenn Sie sagen, dass die zwei Methoden "dasselbe tun", könnte etwas mit Ihrem Entwurf falsch sein. Wenn sie dasselbe tun, warum muss die Elternimplementierung aufgerufen werden, wenn die Unterklasse dasselbe auf eine andere Weise tut?Für mich klingt es wie die Methode tatsächlich tut mehr als eine Sache und Sie könnten in der Lage sein, es in mehrere Teile, die individuell außer Kraft gesetzt werden können (oder nicht, dann machen sie privat oder endgültig).

+0

Ja, "das gleiche" ist hier nicht der richtige Begriff. Diese Methoden haben die gleiche Verantwortung, aber die Unterklassen-Methode erweitert sie um eigene zusätzliche Anforderungen. –