Heim > Backend-Entwicklung > PHP-Tutorial > 浅析PHP中的泛型,了解基础知识

浅析PHP中的泛型,了解基础知识

PHPz
Freigeben: 2022-04-02 19:27:54
nach vorne
5306 Leute haben es durchsucht

本篇文章带大家聊聊PHP中的泛型,介绍一下关于泛型的基础知识,希望对大家有帮助。

浅析PHP中的泛型,了解基础知识

PHP 中的泛型。我知道我想要的就是这个。我知道很多开发者都想要这个使用这个类型。另一方面,也可能有很大规模的一群 PHP 程序员,不知道泛型是什么,或者认为他们为什么要有这个类型。

我将在这个博客上做一个关于泛型和 PHP 的系列文章。让我们从头开始,很快我们就会找到更复杂的话题。我们将讨论什么是泛型,为什么 PHP 不支持它们,未来可能发生什么。

让我们开始吧。

1.png

每种编程语言都有某种类型的系统。有些语言的实现非常严格,而其他语言 ——PHP 属于这一类 —— 则要宽松得多

现在,使用类型系统的原因有很多。 最明显的是类型验证

假设我们有一个接受两个数字、两个整数的函数; 并对它们进行一些数学运算:

function add($a, $b) 
{
    return $a + $b;
}
Nach dem Login kopieren

PHP 允许您将任何类型的数据传递给该函数,数字、字符串、布尔值都无所谓。 PHP 将尽最大努力在有意义的时候转换变量,例如将它们加在一起。

add('1', '2');
Nach dem Login kopieren

但是这些转换 —— 类型杂耍 —— 通常会导致意想不到的结果,或者说是:错误和崩溃。

add([], true); // ?
Nach dem Login kopieren

现在,我们可以手动编写代码来检查我们的数学加法运算,它将被用于任何给定的输入

function add($a, $b) 
{
    if (!is_int($a) || !is_int($b)) {
        return null;
    }
    return $a + $b;
}
Nach dem Login kopieren

或者,我们可以使用 PHPS 内置类型提示–这是我们手动执行操作的内置简写:

function add(int $a, int $b): int 
{
    return $a + $b;
}
Nach dem Login kopieren

PHP 社区中的许多开发人员说他们并不真正关心这些类型提示,因为他们知道自己应该只将整数传递给这个函数 - 毕竟是他们自己写的。

然而,这种推理很快就会瓦解:您通常不是唯一一个在该代码库中工作的人,您还在使用不是您自己编写的代码 - 想想您用 Composer 引入了多少包。因此,虽然这个孤立的示例看起来不是什么大问题,但是一旦您的代码开始增长,类型检查确实会派上用场。

除此之外,添加类型提示不仅可以防止无效状态,而且还澄清我们程序员需要什么样类型的值输入。定义好类型后通常使您无需阅读外部文档,因为函数的大部分功能已经被其类型定义封装。

IDE 大量使用了这一原则:它们可以告诉程序员函数期望什么样类型的值的输入,或者对象上有哪些字段和方法可用 —— 因为它属于一个类。IDE 使我们的代码编写效率更高,这在很大程度上是因为它们可以静态分析我们代码库中的类型提示。

记住这个词:静态分析 —— 这在本系列的后面会非常重要。 这意味着程序、IDE 或其他类型的「静态分析器」可以查看我们的代码,并且在不运行它的情况下告诉我们它是否会工作 —— 至少在某种程度上是这样。如果我们将一个字符串传递给我们的只接受整数的函数,我们的 IDE 会告诉我们我们做错了什么 —— 这会导致程序在运行时崩溃;但我们的 IDE 无需实际运行代码就能告诉我们。

另一方面,类型系统也有其局限性。 一个常见的例子是「项目列表」:

class Collection extends ArrayObject
{
    public function offsetGet(mixed $key): mixed 
    { /* … */ }
    public function filter(Closure $fn): self 
    { /* … */ }
    public function map(Closure $fn): self 
    { /* … */ }
}
Nach dem Login kopieren

一个集合有很多方法可以处理任何类型的输入:循环、过滤、映射,等等;集合实现不应该关心它是处理字符串还是整数。

但是,让我们从局外人的角度来看。如果我们想确保一个集合只包含字符串,而另一个集合只包含「用户」对象,会发生什么。集合本身在循环其 items 时并不关心,但我们关心。我们想知道循环中的这个项目是用户还是字符串 —— 这是完全不同的。但是如果没有正确的类型信息,我们的 IDE 就会在未知情况中运行。

$users = new Collection();
// …
foreach ($users as $user) {
    $user-> // ?
}
Nach dem Login kopieren

现在,我们可以为每个集合创建单独的实现:一个只适用于字符串的实现,另一个只适用于 User 对象:

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

但是如果我们需要第三个实现?第四个?也许 10 个或 20 个。管理这些代码将会变得非常困难。

这就是泛型的用武之地。

需要澄清的是:PHP 没有泛型。这是一个大胆的声明,走了不少弯路,我们将在本系列的后面部分讨论这一点。但是现在我可以说我接下来要展示的内容在 PHP 中是没有的。 但是它存在于其他编程语言中。

许多编程语言允许开发人员在集合类上定义 “泛型”,而不是为每个可能的类型去单独实现:

class Collection<Type> extends ArrayObject
{
    public function offsetGet(mixed $key): Type 
    { /* … */ }
    // …
}
Nach dem Login kopieren

基本上我们说的是集合类的实现适用于任何类型的输入,但是当我们创建集合的实例时,我们应该指定一个类型。它是一个泛型实现,需要根据程序员的需求来特定:

$users = new Collection<User>();

$slugs = new Collection<string>();
Nach dem Login kopieren

添加类型似乎是一件小事。但这种类型本身就开启了一个充满可能性的世界。 我们的 IDE 现在知道了集合中的数据类型,它可以告诉我们是否添加了错误类型的项;它可以告诉我们在迭代集合时可以对项执行什么操作;它可以告诉我们是否将集合传递给知道如何处理这些特定项的函数。

虽然我们可以通过手动为我们需要的每种类型实现一个集合,在技术上实现同样的效果;对于编写和维护代码的开发人员来说,通用实现将是一项重大改进。

那么,我们为什么不在 PHP 中使用泛型呢?除了无聊的收藏,我们还能用它们做什么?我们能为他们增加支持吗?我们将在这个系列中回答所有这些问题。首先需要澄清的是:我在本系列文章中的目标是教你关于泛型的知识,但同样重要的是,我想让大家意识到我们是如何误解 PHP 的。我想改变这种状况。

推荐学习:《PHP视频教程

Verwandte Etiketten:
php
Quelle:learnku.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage