PHP 8.3 新特性 - Override 属性
PHP 8.3 新特性 - Override 属性
hi,我是温新,一名 PHPer
在 PHP 8.3 中,引入了一个新的 #[\Override]
属性,用于注解方法,用于标记一个方法覆盖了父类或接口中的方法。
#[\Override]
可以用在接口、类、Trait、枚举中。
当在子类中定义一个与父类同名的方法时,可以使用 #[\Override]
属性来明确表示该方法是对父类方法的覆盖。这样可以提高代码的可读性,并帮助开发者更好地理解方法的继承关系。
类继承
先来看看 PHP 8.3 之前,子类重写父类的案例。
<?php
class Human {
public function say()
{
echo '人类';
}
}
class Person extends Human {
// 重写父类方法
public function say()
{
echo '王美丽';
}
}
$mei = new Person;
$mei->say();
再来看看 PHP 8.3 及更高版本的写法
class Person extends Human {
<?php
class Human {
public function say()
{
echo '人类';
}
}
class Person extends Human {
// 使用该注解表名这个方法是重写父类的方法
#[\Override]
public function say()
{
echo '王美丽';
}
}
$mei = new Person;
$mei->say();
子类中有 #[\Override]
,而父类中没有,子会报错
PHP Fatal error: Person::say() has #[\Override] attribute, but no matching parent method exists in
也就是说,只要子类有 #[\Override]
,那么父类必需有子类所重写的方法。
#[\Override] 属性类概要
#[Attribute(Attribute::TARGET_METHOD)]
final class Override {
public function __construct() {}
}
-
\Override
属性在全局命名空间中声明。
带有 #[\Override]
属性的类方法必须有一个父方法或接口方法。这个属性在任何具有该属性的 trait/enum/interface/class 方法中都保持一致可用。
接口
<?php
interface Animal {
public function say();
}
interface Dog extends Animal {
#[\Override]
public function say();
}
class Cat implements Dog {
#[\Override]
public function say()
{
echo '喵喵';
}
}
$cat = new Cat;
$cat->say()
这个案例演示了接口的继承的同时,还演示了类实现接口,其中都使用到了 #[\Override]
注解,表明是继承或重写父类方法。
枚举
Enum
不能扩展另一个Enum,但 Enum 仍然可以实现接口,并且 #[\Override]
属性也可以应用于 Enum 方法。
<?php
interface AnimalInterface {
public function say(): void;
}
enum AnimalEnum implements AnimalInterface {
case COLOR;
case AGE;
#[\Override]
public function say(): void {
echo 'hello 来自 AnimalEnum';
}
}
class Cat implements AnimalInterface {
#[\Override]
public function say(): void {
echo 'hello 来自 Cat';
}
}
function callSay(AnimalInterface $instance): void {
$instance->say();
}
callSay(AnimalEnum::COLOR); // hello 来自 AnimalEnum
$cat = new Cat;
callSay($cat); // hello 来自 Cat
Traits
在 traits 中,#[\Override]
方法非常有用。在引入#[\Override]
属性之前,声明 trait 方法并确保使用该 trait 的类将覆盖该方法的唯一方法是将该方法声明为抽象的。
有了#[\Override]
属性,现在可以强制使用它的类覆盖 trait 方法。
<?php
trait MyTrait {
#[\Override]
public function myMethod() {
echo 'MyTrait';
}
}
class MyClass {
use MyTrait;
public function myMethod(): void {
echo "MyClass!";
}
}
function callMyMethod(MyClass $instance): void {
$instance->myMethod();
}
// 创建 MyClass 的实例并调用 myMethod()
$myClass = new MyClass();
callMyMethod($myClass); // 输出: MyClass!
我们来看看下面这种情况,它会报错
<?php
trait MyTrait {
#[\Override]
public function myMethod() {
echo 'MyTrait';
}
}
class MyClass {
use MyTrait;
}
PHP Fatal error: MyClass::myMethod() has #[\Override] attribute, but no matching parent method exists in
在这个案例中,如果 MyClass
没有重写 MyTrait
中的 myMethod()
方法就会报错。从这里可以知道,如果某个 trait 中含有 #[\Override]
标注的方法,那么使用的类中就必需重写被标注的方法。
#[\Override] 是 PHP 8.3 新增的属性。设计上,类的存在不会在编译时进行验证。在先前的 PHP 版本中,向类方法添加 #[\Override] 属性不会有任何效果,但也不会引发任何语法或其他错误。
注意
由于 #
字符在 PHP 中被解释为代码注释,因此在任何 PHP 7 或旧应用程序中添加任何属性都不会引发任何语法错误。
#[\Override] 属性类可以在用户端的 PHP 代码中进行填充。它不会带来功能,但任何检查类方法属性的代码都将能够实例化一个 \Override 实例。
如果任何 PHP 应用程序在全局命名空间中声明自己的 \Override 类,由于用户端的 \Override 类是一个重复声明,这将导致错误。