Maison  >  Article  >  développement back-end  >  Analysons pourquoi les génériques ne peuvent pas être utilisés en PHP

Analysons pourquoi les génériques ne peuvent pas être utilisés en PHP

WBOY
WBOYavant
2022-03-29 10:29:575516parcourir

Cet article vous apporte des connaissances pertinentes sur PHP. Il explique principalement pourquoi les génériques ne peuvent pas être utilisés en PHP. Ensuite, nous examinerons la situation derrière les génériques et PHP pour comprendre pourquoi les génériques ne sont pas encore pris en charge. aide tout le monde.

Analysons pourquoi les génériques ne peuvent pas être utilisés en PHP

Étude recommandée : "Tutoriel PHP"

Pourquoi nous ne pouvons pas utiliser de génériques en PHP

Nous allons approfondir les génériques et ce qui se passe derrière PHP. Il est très intéressant et important de comprendre pourquoi les génériques ne sont pas encore pris en charge en tant que citoyens de premier ordre en PHP.

Analysons pourquoi les génériques ne peuvent pas être utilisés en PHP

Voyons.

Il n'y a pas de génériques en PHP. C’est la conclusion du Nikita de l’année dernière. Ce n’est tout simplement pas réalisable.

Pour comprendre pourquoi Nikita a dit cela, nous devons examiner comment les génériques sont mis en œuvre. De manière générale, il existe trois approches possibles ; les langages de programmation prenant en charge les génériques utilisent principalement l'une de ces trois approches.

Le premier est appelé génériques monomorphes. Revenons au premier article de cette série, dans lequel j'ai montré cet exemple de collection :

class StringCollection extends Collection
{
    public function offsetGet(mixed $key): string 
    { /* … */ }
}
class UserCollection extends Collection
{
    public function offsetGet(mixed $key): User 
    { /* … */ }
}

J'ai expliqué que nous pouvons créer manuellement des implémentations de classes de collection pour chaque type de collection dont nous avons besoin. La charge de travail sera énorme et il y aura beaucoup de code, mais cela fonctionnera.

Les génériques monomorphes font exactement cela, mais automatiquement en coulisses. Au moment de l'exécution, PHP ne connaîtra pas la classe générique Collection, mais plutôt deux ou plusieurs implémentations spécifiques :

$users = new Collection<User>();
// Collection_User
$slugs = new Collection<string>();
// Collection_string

Les génériques monomorphes sont une approche parfaitement valable. Par exemple, Rust les utilise. L'un des avantages de ceci est qu'il existe une série d'améliorations de performances, car il n'y a plus de vérifications de type génériques au moment de l'exécution, ces vérifications sont donc séparées avant d'exécuter le code.

Mais cela nous amène immédiatement au problème des génériques monomorphes en PHP. PHP n'a pas d'étape de compilation explicite comme Rust pour diviser une classe générique en plusieurs implémentations concrètes ; l'essentiel est le suivant : les génériques monomorphes nécessitent un peu de mémoire car vous faites plusieurs copies de la même classe, mais là il y a quelques différences. Ce n'est peut-être pas un gros problème pour les binaires Rust compilés, mais c'est un problème sérieux pour le code PHP exécuté à partir d'un point central (serveur) gérant potentiellement des centaines ou des milliers de requêtes par seconde.

La prochaine option consiste à réifier les génériques. Il s'agit d'une implémentation dans laquelle la classe générique reste telle quelle et les informations de type sont évaluées dynamiquement au moment de l'exécution. C# et Kotlin implémentent les génériques, qui sont les plus proches du système de types actuel de PHP, puisque PHP effectue toutes les vérifications de type au moment de l'exécution. Le problème ici est que cela nécessite beaucoup de refactorisation du code de base pour faire fonctionner les génériques matérialisés, et vous pouvez imaginer qu'à mesure que nous effectuons de plus en plus de vérifications de type au moment de l'exécution, une certaine surcharge de performances augmentera.

Cela nous amène à la dernière option : ignorer complètement les génériques au moment de l'exécution. C'est comme s'ils n'étaient pas là ; après tout, une implémentation générique d'une classe de collection, par exemple, peut de toute façon gérer tous les types d'entrée.

Donc, si nous ignorons toutes les vérifications de type génériques au moment de l'exécution, il n'y aura aucun problème.

Eh bien, pas si vite. Ignorer les types génériques au moment de l'exécution - cela s'appelle d'ailleurs l'effacement de type, et Java et Python le font - a causé quelques problèmes pour PHP.

Un exemple : PHP utilise non seulement des types pour la validation, il utilise également des informations de type pour convertir dynamiquement les valeurs d'un type à un autre - c'est la jonglerie de types que j'ai mentionnée dans le premier article de cette série :

function add(int $a, int $b): int 
{
    return $a + $b;
}
add(&#39;1&#39;, &#39;2&#39;) // 3;

Si PHP ignore le type générique de cette collection "string" et nous y ajoutons accidentellement un entier, il ne parviendra pas à nous avertir si le type générique est supprimé :

$slugs = new Collection<string>();
$slugs[] = 1; // 1 不会被转换为 &#39;1&#39;

Effacement du type Le deuxième problème, le plus important - et peut-être que vous l'avez déjà été crier sur votre écran maintenant - c'est que les genres disparaissent. Si les types génériques sont supprimés au moment de l’exécution, pourquoi les ajoutons-nous ?

Cela a du sens en Java et Pyton car toutes les définitions de type sont vérifiées avant d'exécuter le code avec l'analyseur statique. Java, par exemple, exécute un analyseur statique intégré lors de la compilation de votre code ; ce que PHP ne fait pas du tout : il n'y a pas d'étape de compilation, et certainement pas de vérificateur de type statique intégré.

D'un autre côté… tous les avantages de la vérification de type, ceux dont nous avons parlé dans les articles précédents, ne proviennent pas du vérificateur de type d'exécution intégré à PHP. Nous exécutons déjà le code lorsque le vérificateur de type PHP nous indique qu'il y a un problème. Une erreur de type plante essentiellement notre programme.

Au lieu de cela, la majeure partie de la valeur ajoutée de la vérification de type provient des analyseurs statiques qui ne nécessitent pas que nous exécutions le code. Tant que les programmeurs fournissent suffisamment d’informations sur le type, ils ont de bonnes chances de garantir qu’aucune erreur de type à l’exécution ne se produira. Cela ne signifie pas que vous ne pouvez pas avoir d'erreurs dans votre code, mais il est possible d'écrire du code PHP entièrement vérifié statiquement et qui ne produit aucun type d'erreur au moment de l'exécution. En fin de compte : nous obtenons toutes les informations statiques lors de l'écriture du code ; il s'agit de la partie la plus précieuse de tout système de type, quelle que soit la vérification du type à l'exécution.

Alors, avons-nous vraiment besoin d'une vérification du type d'exécution ? Parce que c'est la principale raison pour laquelle vous ne pouvez pas actuellement ajouter de génériques en PHP : la validation des types génériques au moment de l'exécution est trop complexe ou trop gourmande en ressources pour PHP.

Adresse originale : https://stitcher.io/blog/generics-in-php-3

Adresse de traduction : https://learnku.com/php/t/66486

Apprentissage recommandé : "PHP Tutoriel vidéo

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