为什么使用嵌套特征会改变 PHP 行为?

问题描述 投票:0回答:2

使用 PHP 7.2,我有一个类

MyClass
,它使用了特征
MyFirstTrait
。它的定义是这样的:

class MyClass
{
    use MyFirstTrait;
}

这个

MyFirstTrait
使用了另一个特征
MySecondTrait
。它的定义是这样的:

trait MyFirstTrait
{
    use MySecondTrait;
}

MySecondTrait
不使用任何其他特征。它的定义是这样的:

trait MySecondTrait
{
}

如果我先定义

MyClass
,然后定义特征(特征定义的顺序并不重要),则会引发错误。

该文件将类似于:

// Not working
class MyClass { use MyFirstTrait; }

// These two lines can be swapped, the result is the same.
trait MyFirstTrait { use MySecondTrait; }
trait MySecondTrait { } 

引发的错误是这样的:

Fatal error: Trait 'MyFirstTrait' not found in …

但是,如果我删除嵌套并从

use
中删除
MyFirstTrait
子句,则脚本运行时不会出现错误。如果我先定义特征然后再定义类,也会发生同样的情况。

在第一种情况下,文件将如下所示:

// Working
class MyClass { use MyFirstTrait; }
trait MyFirstTrait { }

第二种情况是这样的:

// Working

// These two lines can be swapped, the result is the same.
trait MyFirstTrait { use MySecondTrait; }
trait MySecondTrait { } 

class MyClass { use MyFirstTrait; }

为什么当特征嵌套时行为会改变?

这对我来说没有多大意义,因为在这两种情况下,所使用的特征都是在引用之后定义的。当移除嵌套并且仅使用单个特征时,在定义类之后定义特征没有问题。

php traits
2个回答
4
投票

从逻辑上讲,您引用的所有内容都应该在引用之前定义。但也有一些例外。退一步来说,PHP 文件的解释分两步:

  1. 标记化和解析。
  2. 解析代码的运行时执行。

一般来说,类将在运行时定义,这意味着代码按照编写的顺序执行。在这里,您必须首先在另一个特征中定义要

use
的特征。但是,一些“简单”特征和类可以由解析器在解析步骤中生成和定义,因此它们将是运行前可用。这纯粹是性能优化。

PHP 到底将什么视为“简单的类/特征”,我不一定会尝试记住或依赖它,因为解析器的功能可能会从一个版本扩展到另一个版本(例如,在某些时候,简单的算术表达式变成了支持像

static $foo = 4 + 2;

 这样的语句,这以前是一个解析错误)。


-1
投票
如何解决这个问题?我有完全相同的问题。

© www.soinside.com 2019 - 2024. All rights reserved.