• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

来为什么不能在PHP使用泛型

武飞扬头像
PHP中文网
帮助30

为什么我们不能在 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 来说,在运行时验证泛型类型太复杂或太耗费资源。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanfhbcg
系列文章
更多 icon
同类精品
更多 icon
继续加载