为什么使用嵌套特征会改变 PHP 行为?
Why does using nested traits change PHP behavior?
使用 PHP 7.2,我有一个使用特征 MyFirstTrait
的 class MyClass
。它是这样定义的:
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 …
但是,如果我删除嵌套并从 MyFirstTrait
中删除 use
子句,脚本运行时不会出错。如果我先定义特征,然后再定义 class.
,也会发生同样的情况
在第一种情况下,文件如下所示:
// 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; }
为什么嵌套特征时行为会发生变化?
这对我来说意义不大,因为在这两种情况下,所使用的特征的定义都晚于它们被引用的时间。当去掉嵌套只使用单个trait时,在定义class.
之后再定义trait是没有问题的
从逻辑上讲,您引用的所有内容都应该在引用之前定义。不过也有一些例外。退一步说,一个PHP文件分两步解释:
- 标记化和解析。
- 解析代码的运行时执行。
一般来说、类会在runtime定义,意思是当代码按顺序执行时书面。在这里,您必须先在另一个特征 中定义要 use
的特征。 然而,一些 "simple" traits 和 类 可以在解析步骤中由解析器生成和定义,因此它们将在运行时 之前可用 。那纯粹是性能优化。
PHP 究竟是什么 "simple class/trait" 并不是我必须要记住或指望的东西,因为解析器的功能可能会从一个版本扩展到另一个版本(例如,在某些时候,像 static $foo = 4 + 2;
这样的语句支持简单的算术表达式,这在以前是一个解析错误)。
使用 PHP 7.2,我有一个使用特征 MyFirstTrait
的 class MyClass
。它是这样定义的:
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 …
但是,如果我删除嵌套并从 MyFirstTrait
中删除 use
子句,脚本运行时不会出错。如果我先定义特征,然后再定义 class.
在第一种情况下,文件如下所示:
// 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; }
为什么嵌套特征时行为会发生变化?
这对我来说意义不大,因为在这两种情况下,所使用的特征的定义都晚于它们被引用的时间。当去掉嵌套只使用单个trait时,在定义class.
之后再定义trait是没有问题的从逻辑上讲,您引用的所有内容都应该在引用之前定义。不过也有一些例外。退一步说,一个PHP文件分两步解释:
- 标记化和解析。
- 解析代码的运行时执行。
一般来说、类会在runtime定义,意思是当代码按顺序执行时书面。在这里,您必须先在另一个特征 中定义要 use
的特征。 然而,一些 "simple" traits 和 类 可以在解析步骤中由解析器生成和定义,因此它们将在运行时 之前可用 。那纯粹是性能优化。
PHP 究竟是什么 "simple class/trait" 并不是我必须要记住或指望的东西,因为解析器的功能可能会从一个版本扩展到另一个版本(例如,在某些时候,像 static $foo = 4 + 2;
这样的语句支持简单的算术表达式,这在以前是一个解析错误)。