Heim  >  Artikel  >  Backend-Entwicklung  >  Analyse von Problemen im Zusammenhang mit PHP7.2, bei dem Methoden der übergeordneten Klasse und das Liskov-Substitutionsprinzip ignoriert werden

Analyse von Problemen im Zusammenhang mit PHP7.2, bei dem Methoden der übergeordneten Klasse und das Liskov-Substitutionsprinzip ignoriert werden

藏色散人
藏色散人nach vorne
2021-11-16 15:14:521351Durchsuche

Erläutern Sie die Unterklassenabdeckungsmethode von PHP 7.2, bei der die Parametertypfunktion und das Liskov-Substitutionsprinzip weggelassen werden.

PHP 7.2 ist schon seit einiger Zeit verfügbar. Wenn Sie sich für die Entwicklung von PHP interessieren, sollten Sie sich über alle neuen Verbesserungen in der Version informiert haben neue Version. Hier werde ich nur eine neue Funktion detailliert beschreiben, die möglicherweise missverstanden wird.

PHP 7.2 kann den von der Methode der übergeordneten Klasse definierten Parametertyp (Typhinweis) ignorieren, wenn die Unterklasse die Methode der übergeordneten Klasse überschreibt:

class Foo
{
    public function bar(SomeClass $obj) {}
}
class Foobar extends Foo
{
    public function bar($obj) {} // 这在 PHP7.2 版本之前是会报错的
}

Ich habe gesehen, dass einige Websites ihren Zweck erwähnt haben, als sie diese Funktion eingeführt haben. Sie soll das Refactoring erleichtern. Wenn sich die Parametertypen der Methode der übergeordneten Klasse in Zukunft ändern, muss die Unterklasse nicht alle ändern. Es klingt vernünftig. Gemäß dieser Aussage lautet die implizite Bedeutung: Wenn die Unterklasse den Parametertyp der Methode der übergeordneten Klasse ignoriert, wird der Parametertyp beim Aufruf weiterhin überprüft. Sie können herausfinden, ob die tatsächliche Situation vorliegt, indem Sie dieses Experiment durchführen:

<?php
class Foo
{
}
class Bar
{
    public function setFoo(Foo $foo)
    {
    }
}
class BarKid extends Bar
{
    public function setFoo($foo)
    {
    }
}
$kid = new BarKid;
$kid->setFoo(&#39;I am a string!&#39;);

Wenn die obige Aussage korrekt ist, sollte setFoo einen Fehler melden, wenn es einen Zeichenfolgenparameter akzeptiert. Der obige Code meldet jedoch keine Fehlermeldung unter 7.2. aber wenn die Unterklasse Wenn die setFoo-Methode einen Parametertyp hinzufügt, wird sofort ein Fehler gemeldet. Denken Sie daran, dass viele Aussagen im Internet nicht vertrauenswürdig sind, mit Ausnahme meiner kleinen Website ...

Das obige Experiment zeigt, dass die Unterklassenmethode Parametertypen weglassen kann und ihr Zweck definitiv nicht darin besteht, das Refactoring zu erleichtern. Was ist also der wahre Zweck?

In PHP 7.1 gibt es eine neue Funktion: „Sie können festlegen, ob die Parameter und der Rückgabetyp einer Methode oder Funktion null sein können“. Es gibt eine Regel, die ziemlich umständlich erscheint: „Der Parametertypbereich der Unterklassenmethode ist gelockert (das heißt, wenn der Parameter der übergeordneten Klasse nicht null sein kann, kann der Parameter der Unterklasse null unterstützen), aber der Rückgabetyp wird verschärft (wenn die Die übergeordnete Klasse kann nicht null zurückgeben, der Unterklassenparameter kann null unterstützen. Die Klasse darf nicht funktionieren. Wenn die übergeordnete Klasse null zurückgeben kann, muss die Unterklasse nicht null zurückgeben „Liskov-Substitutionsprinzip“, gab jedoch keine ausführliche Einführung. Nicht viele PHPer um mich herum achten auf die OOP-Prinzipien, aber ich denke, dass sie jedem Ingenieur bekannt sein sollten, deshalb möchte ich sie vorstellen.

Liskovs Ersetzungsprinzip ist einfach: Wo auch immer die übergeordnete Klasse erscheint, kann sie ausgeführt werden, wenn sie durch eine Unterklasse ersetzt wird, das heißt, die Unterklasse kann die übergeordnete Klasse ohne nachzudenken ersetzen. Tatsächlich denke ich, dass dieses Prinzip aus Sicht des Sprachdesigns die Nachahmung natürlicher Regeln ist 29.09.2018 Ergänzung: Es handelt sich nicht um eine einfache „Nachahmung“. Wenn Sie interessiert sind, können Sie den neuen Blog lesen „Pinguine sind keine Vögel“.

Zum Beispiel können Menschen Alkohol, Tee, Cola und alle Arten von Getränken trinken, aber als Säugetiere können Menschen Wasser trinken, egal was passiert, oder? Aber umgekehrt können Säugetiere Wasser trinken, aber nicht unbedingt Alkohol, Tee oder Cola, daher sind Menschen eine Unterkategorie der Säugetiere.

Aus Sicht des Sprachdesigns sollte eine Unterklasse eine erweiterte Version der übergeordneten Klasse sein, was bedeutet, dass sie in der Lage sein sollte, mehr Objekttypen als die übergeordnete Klasse zu verarbeiten. Die Erweiterung der überschriebenen Methodenparametertypen spiegelt ebenfalls wider dieses Prinzip.

Lassen Sie uns über den Rückgabetyp sprechen, der möglicherweise etwas kompliziert ist. Warum muss eine Unterklasse den Rückgabebereich einschränken? Solange Sie davon ausgehen, dass die Rückgabe einer Methode als Parameter einer anderen Methode verwendet wird, ist es tatsächlich leicht, darüber nachzudenken. Beispielsweise verfügt eine „Fruit Beverage Factory“-Klasse über eine „Production“-Methode, die „Fruit Juice“ zurückgibt und an die „Drink“-Methode von „Kid“ übergibt. Es gibt eine „Orangensaftfabrik“, die eine Unterklasse der „Fruchtgetränkefabrik“ ist. Der Rückgabetyp ihrer „Produktion“-Methode ist eingeschränkt und kann nur „Orangensaft“ zurückgeben. trinken“ und wird nicht angezeigt. Noch Fragen.

Nennen Sie ein weiteres Gegenbeispiel. Wenn eine weitere Unterklasse von „Fruit Beverage Factory“ erscheint und deren „Produktions“-Methode neben Fruchtsaft auch Fruchtwein zurückgeben kann, kann diese Unterklasse die übergeordnete Klasse offensichtlich nicht ersetzen, da die Gefahr besteht, dass Kinder trinken.

Nachdem wir über das Ersetzungsprinzip von Liskov gesprochen haben, werfen wir einen Blick auf diese Verbesserung in 7.2. Zu diesem Zeitpunkt sollten wir wissen, dass dies tatsächlich eine Manifestation des Liskov-Prinzips ist. Derzeit ist die Implementierung des Substitutionsprinzips in PHP unvollständig. Einige Leute denken vielleicht, dass diese Version auch „die übergeordnete Klasse hat keinen Rückgabetyp und die Unterklasse kann einen Rückgabetyp haben“ unterstützt? Leider wird es zumindest in Version 7.2 nicht unterstützt. Sie können selbst experimentieren.

Eine weitere neue Funktion in 7.2 ist, dass „Objekt“ als Typ eines beliebigen Objekts verwendet werden kann. Siehe das offizielle Beispiel:

<?php
function test(object $obj) : object
{
    return new SplQueue();
}
test(new StdClass());

Tatsächlich gab es vor der Veröffentlichung von 7.2, ebenfalls basierend auf dem Substitutionsprinzip, eine Frage dazu, „ob Unterklassen Objekttypen verwenden können, um die Typen überschriebener Methodenobjektparameter zu ersetzen“, aber die Die endgültige Abstimmung wurde nicht angenommen. Obwohl ich den Grund nicht kenne, hat ihn zumindest jemand erwähnt.

Darüber hinaus kann PHP derzeit nicht wie Java überladen und es gibt keine Möglichkeit, den Typ der überschriebenen Methode anzugeben (derzeit kann der Typ nur direkt entfernt werden, was etwas zu grob ist):

<?php
class Foo
{
}
class FooFoo extends Foo
{
}
class Bar
{
    public function foo(FooFoo $foo)
    {
    }
}
class BarBar extends Bar
{
    public function foo(Foo $foo) // 依然会报『子类不兼容父类方法格式』的错误
    {
    }
}

Aber PHP ist ständig sich ändern, oder? Die PHP-Version hat sich in letzter Zeit so schnell entwickelt, und ich bin sehr zuversichtlich, dass PHP eine Sprache werden wird, die mehr OOP-Funktionen unterstützt!

Empfohlenes Lernen: „PHP7-Tutorial

Das obige ist der detaillierte Inhalt vonAnalyse von Problemen im Zusammenhang mit PHP7.2, bei dem Methoden der übergeordneten Klasse und das Liskov-Substitutionsprinzip ignoriert werden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:chrisyue.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen