控制匿名类的使用

根据匿名类的定义,它没有名称。不过,为了提供信息,PHP 信息函数(如 var_dump()var_ export()get_class()Reflection 扩展中的其他类)将匿名类简单地报告为 class@anonymous。然而,当一个匿名类扩展了另一个类或实现了一个接口时,让 PHP 信息函数反映这一事实可能会有些用处。

在 PHP 8 中,扩展了一个类或实现了一个接口的匿名类现在通过将分配给匿名类的标签更改为 Xyz@anonymous(其中 Xyz 是类或接口的名称)来反映这一事实。如果匿名类实现了多个接口,则只会显示第一个接口。如果匿名类扩展了一个类,同时也实现了一个或多个接口,它所扩展的类的名称就会出现在标签中。下表总结了这些可能性:

Table 1. Table 9.4 – Anonymous class promotion
上下文 新名称

extends Xyz

Xyz@anonymous

implements Abc

Abc@anonymous

implements Abc, Def

Abc@anonymous

extends Xyz implements Abc

Xyz@anonymous

请记住,PHP 已经可以测试匿名类是否属于某一继承关系。例如,instanceof 操作符就可以用于此目的。下面的示例说明了如何测试匿名类的继承性,以及如何查看它的新名称:

  1. 在本例中,我们将定义一个 DirectoryIterator 实例,用于从当前目录抓取文件列表:

    // /repo/ch09/php8_oop_diff_anon_class_renaming.php
    $iter = new DirectoryIterator(__DIR__);
  2. 然后,我们将定义一个扩展 FilterIterator 的匿名类。在这个类中,我们将定义 accept() 方法,该方法会产生一个布尔结果。如果结果为 TRUE,那么该项目将出现在最终迭代中:

    $anon = new class ($iter) extends FilterIterator {
        public $search = '';
        public function accept() {
            return str_contains(
                $this->current(), $this->search);
        }
    };
  3. 接下来,我们将生成名称中包含 bc_break 的文件列表:

    $anon->search = 'bc_break';
    foreach ($anon as $fn) echo $fn . "\n";
  4. 在接下来的两行中,我们将使用 instanceof 来测试匿名类是否实现了 OuterIterface

    if ($anon instanceof OuterIterator)
        echo "This object implements OuterIterator\n";
  5. 最后,我们将使用 var_dump() 简单地转储匿名类的内容:

    echo var_dump($anon);

下面是在 PHP 8 下运行的输出结果。我们无法在 PHP 7 中运行此示例,因为该版本缺少 str_contains() 函数!

root@php8_tips_php8 [ /repo/ch09 ]#
php php8_oop_diff_anon_class_renaming.php
php8_bc_break_construct.php
php8_bc_break_serialization.php
php8_bc_break_destruct.php
php8_bc_break_sleep.php
php8_bc_break_scanner.php
php8_bc_break_serializable.php
php8_bc_break_magic_wrong.php
php8_bc_break_magic.php
php8_bc_break_magic_to_string.php
This object implements OuterIterator
object(FilterIterator@anonymous)#2 (1) {
  ["search"]=> string(8) "bc_break"
}

正如您所看到的,instanceof 正确报告匿名类实现了 OuterInterface(因为它扩展了 FilterIterator,而 FilterIterator 又实现了 OuterInterface)。 您还可以看到 var_dump() 将匿名类的名称报告为 FilterIterator@anonymous

现在您已经了解了 PHP 8 中匿名类命名的变化,让我们看看命名空间处理方面的变化。