web-dev-qa-db-fra.com

Pourquoi la substitution de paramètres de méthode est-elle une violation des normes strictes en PHP?

Je sais qu'il y a quelques questions similaires ici dans StackOverflow comme cette question .

Pourquoi la substitution de paramètres de méthode est-elle une violation des normes strictes en PHP? Par exemple:

class Foo
{
    public function bar(Array $bar){}
}

class Baz extends Foo
{
    public function bar($bar) {}
}

Normes strictes: la déclaration de Baz :: bar () doit être compatible avec celle de Foo :: bar ()

Dans d'autres langages de programmation OOP vous pouvez. Pourquoi est-ce mauvais en PHP?

41
Kaern Stone

En POO, [[# #]] solide [~ # ~] signifie responsabilité unique, ouvert-fermé, substitution Liskov, ségrégation d'interface et inversion de dépendance .

substitution Liskov le principe stipule que, dans un programme informatique, si Bar est un sous-type de Foo, alors les objets de type Foo peuvent être remplacés par des objets de type Bar sans altérer aucune des propriétés souhaitées de ce programme (exactitude, tâche effectuée, etc.).

Dans les langages de programmation de type fort, lorsque vous remplacez une méthode Foo, si vous changez la signature dans Bar, vous êtes en fait surcharge puisque la méthode d'origine et la nouvelle méthode sont disponibles avec des signatures différentes. Puisque PHP est de type faible, cela n'est pas possible à réaliser, car le compilateur ne peut pas savoir laquelle des méthodes vous appelez réellement. (D'où la raison pour laquelle vous ne pouvez pas avoir 2 méthodes avec même nom, même si leurs signatures sont différentes).

Ainsi, pour éviter la violation du principe de substitution de Liskov, un avertissement standard strict est émis, indiquant au programmeur que quelque chose pourrait casser en raison du changement de la signature de la méthode dans la classe enfant.

51
Tivie

Je sais que je suis en retard à la fête, mais les réponses n'énoncent pas vraiment le problème réel.

Le problème est PHP ne prend pas en charge la surcharge de fonction/méthode. Il serait difficile de prendre en charge la surcharge de fonction dans un langage non typé.

Faire allusion aide. mais en PHP c'est très limité. Je ne sais pas pourquoi. Par exemple, vous ne pouvez pas laisser entendre qu'une variable est un entier ou un booléen mais que le tableau est correct. Allez comprendre!

D'autres langages orientés objet implémentent cela en utilisant la surcharge de fonctions. C'est-à-dire que la signature de la fonction est évidemment différente.

Ainsi, par exemple, si ce qui suit était possible, nous n'aurions pas de problème

class Foo
{
    public function bar(Array $bar){
        echo "Foo::bar";
    }
}

class Baz extends Foo
{
    public function bar(int $bar) {
        echo "Baz::bar";
    }
}


$foo = new Baz();
$bar = new Baz();
$ar = array();
$i = 100;

$foo->bar($ar);
$bar->bar((int)$i);

would output

Foo::bar
Baz::bar

Bien sûr, en ce qui concerne les constructeurs, les développeurs php ont réalisé qu'ils devaient l'implémenter, que cela vous plaise ou non! Donc, ils suppriment simplement l'erreur ou ne la soulèvent pas dans le premier cas.

C'est idiot.

Une connaissance a dit un jour PHP implémenté des objets uniquement comme un moyen d'implémenter des espaces de noms. Maintenant, je ne suis pas tout à fait critique, mais certaines des décisions prises ont tendance à soutenir cette théorie.

J'ai toujours un maximum d'avertissements activé lors du développement de code, je ne laisse jamais passer un avertissement sans comprendre ce que cela signifie et quelles sont les implications. Personnellement, je ne me soucie pas de cet avertissement. Je sais ce que je veux faire et PHP ne le fait pas correctement. Je suis venu ici à la recherche d'un moyen de le supprimer sélectivement. Je n'ai pas encore trouvé de moyen.

Je vais donc piéger cet avertissement et le supprimer moi-même. Dommage que je doive faire ça. mais je suis strict au sujet de STRICT.

18
DeveloperChris

Vous pouvez remplacer les paramètres, mais la signature doit correspondre. Si vous aviez mis Array devant $bar, il n'y aurait pas de problème.

Par exemple, si vous aviez ajouté un paramètre supplémentaire, il n'y aurait aucun problème, à condition que le premier paramètre ait le même type d'indication. C'est une bonne pratique dans n'importe quelle langue.

4
Brad

Parce que vous avez déclaré sur Foo que $bar Devrait être de type array, tandis que dans l'extension Bar, le type de $bar Isn ' t déclaré.

Ce n'est pas une erreur, c'est un avertissement. Vous devez rendre la définition de méthode compatible avec la classe de base d'origine. Vous pouvez cependant l'ignorer en toute sécurité si vous savez ce que vous faites (et niquement si vous savez ce que vous faites !!!)

2
Madara Uchiha