"Überladen" einer privaten Methode in PHP

8

Ich weiß, ich kann Methoden in PHP nicht überladen. Und soweit ich weiß, sind private -Methoden in einer Klasse für Klassen unsichtbar, die die Basisklasse erweitern. Warum funktioniert das nicht?

%Vor%

Der Fehler:

PHP Strict Standards: Declaration of Child::foo() should be compatible with Base::foo($arg) in /var/www/boludo.php on line 17

Ich nahm an, dass die Methode foo($arg) in der Klasse Child unsichtbar ist, weil private ist. Also, ich überbelaste foo nicht, ich erstelle nur eine Methode namens foo .

    
Enrique Marcos 17.08.2013, 12:22
quelle

2 Antworten

3

Um den Hinweis zu korrigieren, ändern Sie einfach foo() im Child zu

%Vor%

Zur Frage "Warum funktioniert das nicht?":

Die Sichtbarkeit in PHP bezieht sich ausschließlich auf den Laufzeitzugriff. Es beeinflusst nicht, wie Sie Klassen und Methoden erweitern / verfassen / überladen können. Wenn Sie die Sichtbarkeit einer privaten Methode von einem Supertyp in einem Subtyp entfernen, wird eine separate Methode im Subtyp hinzugefügt, die nicht auf dieselbe benannte Methode im Supertyp zugreifen kann. PHP wird jedoch für diese eine Eltern-Kind-Beziehung annehmen. Das hat die Benachrichtigung jedoch nicht verursacht. Zumindest nicht auf eigene Faust.

Der Grund, warum Sie den Hinweis bekommen, ist, dass Sie dann auch versuchen, die Methodensignatur zu ändern. Für Ihre foo() muss nicht mehr $arg an sie übergeben werden. Wenn Sie eine Eltern-Kind-Beziehung zwischen den Methoden annehmen, ist das ein Problem, weil das Liskow-Substitutionsprinzip angibt, dass "Wenn S ein Untertyp von T ist, dann können Objekte des Typs T durch Objekte des Typs S ersetzt werden, ohne das Programm zu unterbrechen. Mit anderen Worten: Wenn Sie Code haben, der Base verwendet, sollten Sie in der Lage sein, Base durch Child zu ersetzen, und das Programm sollte immer noch so arbeiten, als ob es Base verwendet hätte.

Angenommen, Ihre Base hat auch eine öffentliche Methode bar() .

%Vor%

Stellen Sie sich jetzt Child changes bar() vor, um ein Argument zu verlangen. Wenn Sie dann Child für Base an den Client übergeben, brechen Sie den Client, weil der Client $base->bar(); ohne ein Argument aufruft.

Offensichtlich könnten Sie den Client ändern, um ein Argument zu übergeben, aber dann hängt der Code wirklich davon ab, wie Child die Methode definiert hat, also ist der Typhint falsch. Tatsächlich ist Child kein Base , weil es sich nicht wie ein Base verhält. Es ist dann Erbschaft gebrochen.

Nun das Lustige ist, wenn Sie das $arg von foo() entfernen, verletzen Sie technisch LSP nicht, weil der Client immer noch funktionieren würde. Die Nachricht ist hier falsch. Das Aufrufen von $base->foo(42) in einem Client, der zuvor Base verwendet hat, funktioniert immer noch mit einem Child , weil% code_de% das Argument einfach ignorieren kann. Aber PHP möchte, dass Sie das Argument optional machen.

Beachten Sie, dass LSP auch auf die Rückgabe einer Methode angewendet wird. PHP enthält nur den Rückgabetyp in der Signatur nicht, so dass Sie dies selbst berücksichtigen müssen. Ihre Methoden müssen zurückgeben, was der Supertype zurückgegeben hat oder was verhaltensmäßig äquivalent ist.

    
Gordon 17.08.2013, 14:39
quelle
3

Sie können das Überladen von Funktionen in PHP mit der Funktion __call durchführen: Ссылка

Abgesehen davon besteht Ihr Problem darin, dass Sie auf diese Weise gegen das Prinzip der Substituierbarkeit verstoßen: Ссылка

Etwas, das PHP benutzt. Auf diese Weise wird die Ersetzbarkeit verletzt, wenn Sie ein Objekt vom Typ Basistyp durch eines mit dem Typ Child ersetzen. Sie ändern die Schnittstelle der Basisklasse in der abgeleiteten Klasse und entfernen das Argument der Methode foo (...). Auf diese Weise können Objekte der Basisklasse nicht durch Objekte der Klasse Child ersetzt werden, ohne das Programm zu unterbrechen. damit verletzt Liskovs Substituierbarkeitsprinzip (LSP).

    
Nick L. 17.08.2013 12:58
quelle

Tags und Links