为什么使用嵌套特征会改变 PHP 行为? [英] Why does using nested traits change PHP behavior?

查看:26
本文介绍了为什么使用嵌套特征会改变 PHP 行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 PHP 7.2,我有一个使用特征 MyFirstTrait 的类 MyClass.它是这样定义的:

Using PHP 7.2, I have a class MyClass that uses a trait MyFirstTrait. It is defined like this:

class MyClass
{
    use MyFirstTrait;
}

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

This MyFirstTrait uses another trait MySecondTrait. It is defined like this:

trait MyFirstTrait
{
    use MySecondTrait;
}

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

MySecondTrait does not use any other traits. It is defined like this:

trait MySecondTrait
{
}

如果我先定义 MyClass 再定义特征(定义特征的顺序无关紧要),则会引发错误.

If I define MyClass first and then the traits (it does not matter in which order the traits are defined), an error is raised.

文件应该是这样的:

// 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 子句,则脚本运行不会出错.如果我先定义特征,然后定义类,也会发生同样的情况.

However, if I remove the nesting and remove the use clause from MyFirstTrait, the script runs without errors. The same happens if I define the traits first and then the class.

在第一种情况下,文件看起来像这样:

In the first case, the file would look like this:

// 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; }

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

Why does the behavior change when the traits are nested?

这对我来说没有多大意义,因为在这两种情况下,使用的特征定义晚于它们被引用.当去掉嵌套,只使用单个trait时,定义类之后再定义trait就没有问题了.

It doesn’t make much sense to me, because in both cases, the used traits are defined later than they are referenced. When the nesting is removed and only single trait is used, there is no problem with the trait being defined after defining the class.

推荐答案

从逻辑上讲,您引用的所有内容都应该在引用之前进行定义.不过也有一些例外.退一步,一个PHP文件被解释为两步:

Logically, everything you refer to should be defined before you refer to it. There are some exceptions to this though. Taking a step back, a PHP file is interpreted in two steps:

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

一般来说,类将在运行时定义,这意味着代码按照编写的顺序执行.在这里,您必须首先在另一个特征中使用定义特征.但是,一些简单"特征和类可以是由解析器在解析步骤中生成和定义,因此它们将在运行前可用.这纯粹是一种性能优化.

Generally speaking, classes will be defined at runtime, meaning when the code is executed in the order it is written. Here you must have defined the trait you're going to use in another trait first. However, some "simple" traits and classes can be generated and defined by the parser in the parsing step, so they will be available before runtime. That is purely a performance optimisation.

PHP 究竟将什么视为简单的类/特征"并不是我必须要记住或指望的东西,因为解析器的功能可能会从一个版本扩展到另一个版本(例如,在某些时候简单的算术表达式变得支持像 static $foo = 4 + 2; 这样的语句,这在以前是一个解析错误).

What exactly PHP regards as a "simple class/trait" is not something I would necessarily try to remember or count on, as the capabilities of the parser may expand from one version to another (for instance, at some point simple arithmetic expressions became supported for statements like static $foo = 4 + 2;, which was previously a parse error).

这篇关于为什么使用嵌套特征会改变 PHP 行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆