Maison  >  Article  >  développement back-end  >  Analyse des problèmes liés à PHP7.2 ignorant les méthodes de classe parent et le principe de substitution de Liskov

Analyse des problèmes liés à PHP7.2 ignorant les méthodes de classe parent et le principe de substitution de Liskov

藏色散人
藏色散人avant
2021-11-16 15:14:521351parcourir

Élaborez la méthode de couverture des sous-classes de PHP 7.2 en omettant la fonction de type de paramètre et le principe de substitution de Liskov

PHP 7.2 est disponible depuis un certain temps. Tant que vous vous souciez du développement de PHP, vous devriez avoir lu les nouvelles améliorations apportées au. nouvelle version. Ici, je ne détaillerai qu'une nouvelle fonctionnalité qui pourrait être mal comprise.

PHP 7.2 peut ignorer le type de paramètre (indice de type) défini par la méthode de la classe parent lorsque la sous-classe remplace la méthode de la classe parent :

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

J'ai vu que certains sites Web ont mentionné son objectif lors de l'introduction de cette fonction. Si les types de paramètres de la méthode de la classe parent changent à l'avenir, la sous-classe n'a pas besoin de tous les modifier." Cela semble raisonnable. Selon cette déclaration, la signification implicite est la suivante : si la sous-classe ignore le type de paramètre de la méthode de la classe parent, le type de paramètre sera toujours vérifié lors de son appel. Vous pouvez découvrir si la situation réelle est la suivante en faisant cette expérience :

<?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;);

Si l'instruction ci-dessus est correcte, setFoo devrait signaler une erreur lorsqu'il accepte un paramètre de chaîne. Cependant, le code ci-dessus ne signale aucun message d'erreur sous 7.2, mais si la sous-classe Si la méthode setFoo ajoute un type de paramètre, une erreur sera immédiatement signalée. N'oubliez pas que de nombreuses déclarations sur Internet ne sont pas fiables, à l'exception de mon petit site Web...

L'expérience ci-dessus montre que la méthode de sous-classe peut omettre les types de paramètres et que son objectif n'est certainement pas de faciliter la refactorisation. Alors, quel est le véritable objectif ?

Il y a une nouvelle fonctionnalité dans PHP 7.1, qui est "Vous pouvez définir si les paramètres et le type de retour d'une méthode ou d'une fonction peuvent être nuls". Il y a une règle qui semble plutôt délicate : "La plage de types de paramètres de la méthode de sous-classe est assouplie (c'est-à-dire que si le paramètre de classe parent ne peut pas être nul, le paramètre de sous-classe peut prendre en charge null), mais le type de retour est resserré (si le paramètre de sous-classe peut prendre en charge null). la classe parent ne peut pas renvoyer null, le paramètre de sous-classe peut prendre en charge null). La classe ne doit pas fonctionner ; si la classe parent peut renvoyer null, la sous-classe n'a pas besoin de renvoyer null)" J'ai brièvement dit à l'époque que c'était à cause du "Principe de substitution de Liskov", mais n'a pas donné une introduction approfondie. Peu de PHP autour de moi prêtent attention aux principes de la POO, mais je pense que tous les ingénieurs devraient le connaître, j'aimerais donc le présenter.

Le principe de remplacement de Liskov est simple : partout où la classe parent apparaît, elle peut être exécutée si elle est remplacée par une sous-classe, c'est-à-dire que la sous-classe peut remplacer la classe parent sans réfléchir. En fait, du point de vue de la conception du langage, je pense que ce principe est l'imitation de règles naturelles2018-09-29 Supplément : Ce n'est pas une simple "imitation". Si vous êtes intéressé, vous pouvez lire le nouveau blog. "Les pingouins ne sont pas des oiseaux".

Par exemple, les gens peuvent boire de l'alcool, du thé, du cola et toutes sortes de boissons, mais en tant que mammifères, les humains peuvent boire de l'eau quoi qu'il arrive, n'est-ce pas ? Mais à l’inverse, les mammifères peuvent boire de l’eau, mais ils ne sont pas nécessairement capables de boire de l’alcool, du thé ou du cola, les humains sont donc une sous-catégorie de mammifères.

Du point de vue de la conception du langage, une sous-classe doit être une version améliorée de la classe parent, ce qui signifie qu'elle doit être capable de gérer plus de types d'objets que la classe parent. L'expansion des types de paramètres de méthode remplacés est également le reflet de. ce principe.

Parlons du type de retour, qui peut être un peu compliqué. Pourquoi une sous-classe doit-elle réduire la plage de retour ? En fait, tant que l’on suppose que le retour d’une méthode sera utilisé comme paramètre d’une autre méthode, il est facile d’y penser. Par exemple, une classe « Fruit Beverage Factory » a une méthode « Production » qui renvoie « Fruit Juice » et le transmet à la méthode « Drink » du « Kid ». Il existe une classe « Orange Juice Factory » qui est une sous-classe de « Fruit Beverage Factory ». Le type de retour de sa méthode « Production » est restreint et ne peut renvoyer que « Orange Juice ». boire" et n'apparaîtra pas. Des questions.

Citer un autre contre-exemple. Si une autre sous-classe de « Fruit Beverage Factory » apparaît et que sa méthode de « Production » peut renvoyer du vin de fruit en plus du jus de fruit, alors cette sous-classe ne peut évidemment pas remplacer la classe parent au risque de boire pour les enfants.

Après avoir parlé du principe de remplacement de Liskov, jetons un coup d'œil à cette amélioration en 7.2. Nous devrions savoir à ce stade qu'il s'agit en fait d'une manifestation du principe de Liskov. Actuellement, la mise en œuvre du principe de substitution en PHP est incomplète. Certaines personnes peuvent penser que cette version prend également en charge « la classe parent n'a pas de type de retour et la sous-classe peut avoir un type de retour » ? Malheureusement, au moins dans la version 7.2, cela n'est pas pris en charge. Vous pouvez expérimenter par vous-même.

Une autre nouvelle fonctionnalité de la version 7.2 est que l'objet peut être utilisé comme type de n'importe quel objet. Voir l'exemple officiel :

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

En fait, avant la sortie de la version 7.2, également basée sur le principe de substitution, il y avait une question de savoir "si les sous-classes peuvent utiliser des types d'objet pour remplacer les types de paramètres d'objet de méthode remplacés", mais le le vote final n'a pas été adopté. Même si je ne connais pas la raison, au moins quelqu'un l'a mentionné.

De plus, actuellement PHP ne peut pas surcharger comme Java, et il n'y a aucun moyen de spécifier le type de la méthode remplacée (actuellement, le type ne peut être supprimé que directement, ce qui est un peu trop approximatif) :

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

Mais PHP est constamment ça change, non ? La version PHP a été itérée si rapidement récemment, et je suis convaincu que PHP deviendra un langage prenant en charge davantage de fonctionnalités POO !

Apprentissage recommandé : "Tutoriel PHP7"

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer