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

时间:2018-01-24 07:38:42

标签: php traits

使用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; }

为什么在嵌套特征时行为会发生变化?

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

1 个答案:

答案 0 :(得分:3)

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

  1. 令牌化和解析。
  2. 运行时执行已解析的代码。
  3. 一般来说,类将在 runtime 中定义,这意味着代码按照编写顺序执行。在这里,你必须首先在另一个特征中定义你要去use的特征。但是,可以生成和定义一些“简单”特征和类解析器中的解析器,因此它们将在运行时之前可用。这纯粹是一种性能优化。

    由于解析器的功能可能会从一个版本扩展到另一个版本(例如,在某些时候简单算术),因此PHP认为“简单类/特征”不是我必须尝试记住或依赖的东西。表达式变得支持像static $foo = 4 + 2;之类的语句,这在以前是一个解析错误。)