一起来分析为什么不能在PHP中使用泛型

一起来分析为什么不能在PHP中使用泛型,第1张

一起来分析为什么不能在PHP中使用泛型 本篇文章给大家带来了关于PHP的相关知识,主要介绍了为什么不能在PHP中使用泛型,下面将深入探讨泛型和PHP背后的情况,理解为什么泛型还不被支持作为一等公民,希望对大家有帮助。

推荐学习:《PHP教程》

为什么我们不能在 PHP 中使用泛型

我们将深入探讨泛型和 PHP 背后的情况。理解为什么泛型在 PHP 中还不被支持作为一等公民,这非常有趣,并且非常重要。

让我们看看吧。

PHP 中没有泛型。这就是去年的 Nikita 的结论。这根本不可行。

为了理解 Nikita 为什么这么说,我们需要看看如何实现泛型。一般来说,有三种可能的方法;支持泛型的编程语言大多使用这三种方法之一。

第一个称为 单态泛型。 让我们回到这个系列的第一篇文章,在这篇文章中我展示了这个集合示例:

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

我解释了我们可以为需要的集合的每种类型,手动创建集合类的实现。 工作量将是巨大的,会有很多代码,但是它会起作用。

单态泛型正是这样做的,但在幕后自动实现。 在运行时,PHP 不会知道泛型 Collection 类,而是知道两个或多个特定实现:

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

单态泛型是一种完全有效的方法。例如,Rust 就使用它们。 其一个优点是有一系列的性能提升,因为在运行时没有更多的泛型类型检查,所以在运行代码之前,这些检查都是分开的。

但是这立刻让我们想到了 PHP 中单态泛型的问题。 PHP 没有像 Rust 那样将一个泛型类分成几个具体实现的显式编译步骤;最重要的是:单态泛型确实需要相当多的内存,因为你在制作同一个类的多个副本,但有一些差异。 对于已编译的 Rust 二进制文件来说,这可能不是一个大问题,但对于从中心点(服务器)运行的 PHP 代码来说,这是一个严重的问题;可能每秒处理数百或数千个请求。

下一个选项是具体化泛型。这是一个实现,其中泛型类保持原样,类型信息在运行时动态评估类型信息。C# 和 Kotlin 实现了泛型,它是最接近 PHP 当前类型系统的,因为 PHP 在运行时执行所有类型检查。这里的问题是需要大量的核心代码重构才能使具体化泛型发挥作用,你可以想象,随着我们在运行时进行越来越多的类型检查,一些性能开销会逐渐增加。

这将我们带到最后一个选项:在运行时完全忽略泛型。就像它们不在那里一样;毕竟,例如集合类的泛型实现无论如何都可以处理所有类型的输入。

因此,如果我们在运行时忽略所有泛型类型检查,则不会有任何问题。

好吧,没有那么快。 在运行时忽略泛型类型 —— 顺便说一下,它被称为类型擦除,Java 和 Python 会这样做 —— 这给 PHP 带来了一些问题。

举一个例子:PHP 不仅使用类型进行验证,它还使用类型信息将值从一种类型动态转换为另一种类型 —— 这就是我在本系列的第一篇文章中提到的类型杂耍:

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

如果 PHP 忽略了这个「字符串」集合的泛型类型,并且我们不小心向它添加了一个整数,那么如果泛型类型被删除,它将无法警告我们:

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

类型擦除的第二个也是更重要的问题 —— 也许你现在已经在屏幕上大喊大叫了 —— 是类型消失了。如果泛型类型在运行时被删除,我们为什么要添加它们?

这在 Java 和 Pyton 中是有意义的,因为在使用静态分析器运行代码之前会检查所有类型定义。 例如,Java 在编译代码时会运行一个内置的静态分析器; PHP 根本不会做的事情:没有编译步骤,当然也没有内置的静态类型检查器。

另一方面…… 类型检查的所有优点,我们在之前的文章中讨论过的那些;它们不是来自 PHP 的内置运行时类型检查器。当 PHP 的类型检查器告诉我们有问题时,我们已经在运行代码了。一个类型错误本质上是让我们的程序崩溃。

相反,类型检查的大部分附加值来自不需要我们运行代码的静态分析器。只要程序员提供足够的类型信息,他们就能很好地确保不会出现运行时类型错误。这并不意味着你的代码中不能有任何错误,但可以编写完全静态检查并且在运行时不会产生任何类型错误的 PHP 代码。最重要的是:我们在编写代码时获得了所有静态洞察;这是任何类型系统中最有价值的部分,与运行时类型检查无关。

那么我们真的需要运行时类型检查吗?因为这是目前无法在 PHP 中添加泛型的主要原因:对于 PHP 来说,在运行时验证泛型类型太复杂或太耗费资源。

原文地址:https://stitcher.io/blog/generics-in-php-3

译文地址:https://learnku.com/php/t/66486

推荐学习:《PHP视频教程》

以上就是一起来分析为什么不能在PHP中使用泛型的详细内容,

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/679093.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-19
下一篇 2022-04-19

发表评论

登录后才能评论

评论列表(0条)

保存