在 PHP 8.1 中,以下代码在以前的版本中有效:
class Example implements Countable {
public function count() {
return 42;
}
}
Run Code Online (Sandbox Code Playgroud)
提出弃用通知:
已弃用:Example::count() 的返回类型应与 Countable::count(): int 兼容,或者应使用 #[\ReturnTypeWillChange] 属性暂时抑制通知
这是什么意思,我应该如何解决它?
IMS*_*SoP 63
从 PHP 7.0 开始,可以指定函数或方法的返回类型,例如function example(): string指示返回字符串的函数。这形成了其他代码可以依赖的契约。
例如,此类承诺该getList方法将返回某种类型Iterator:
class Base {
public function getList(): Iterator {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
编写调用代码时可以知道如果$foo instanceOf Base为真,那么$foo->getList() instanceOf Iterator也将为真。
如果扩展该类,则可以指定相同的返回类型或更具体的返回类型(称为“协方差”的规则),并且调用代码的假设仍然为真:
class SubClass extends Base {
public function getList(): DirectoryIterator {
// ...
}
}
$foo = new SubClass;
var_dump($foo instanceOf Base); // true
var_dump($foo->getList() instanceOf Iterator); // true
Run Code Online (Sandbox Code Playgroud)
但是,如果您指定不同的返回类型,或者根本没有返回类型,则假设将被破坏,因此 PHP 将不允许您这样做:
class NotPossible extends Base {
public function getList(): bool {
return false;
}
}
// Fatal error: Declaration of NotPossible::getList(): bool must be compatible with Base::getList(): Iterator
// If the error didn't happen...
$foo = new NotPossible;
var_dump($foo instanceOf Base); // would be true
var_dump($foo->getList() instanceOf Iterator); // would be false!
Run Code Online (Sandbox Code Playgroud)
如果将返回类型添加到现有的类或接口,则每个扩展或实现的类也必须更改,否则将给出与NotPossible上例相同的错误。
PHP 8.0中增加了Union Types,可以指定大多数内部函数和方法的返回类型;但是为任何未标记的类或接口方法指定它final会立即破坏大量代码。
因此,相反,添加了“暂定”返回类型的概念:记录了正确的返回类型,但通常是错误的是问题中显示的弃用通知。
#[\ReturnTypeWillChange]额外的问题是,很多代码需要能够在多个版本的 PHP 上运行,并且一些添加的返回类型在 8.0 之前的版本中无效。因此,要指示对代码中返回类型的计划更改,您可以添加特殊属性 #[\ReturnTypeWillChange]。这看起来像是对旧版本 PHP 的注释,但告诉 PHP 8.1 不要提出弃用通知。然后,一旦不需要支持旧版本的 PHP,就可以修复返回类型。
首先,仔细阅读消息,找出需要更改哪个方法,以及正确的返回类型是什么。在上面的例子中:
Example::count() 的返回类型 ...
这表示count该类的方法Example需要更改......
...应该与 Countable::count(): int ...兼容
...预期的返回类型是,如接口int上所定义Countable
接下来,决定你可以做什么:
42对于返回类型有效int。extend。如果您正在处理用户可能扩展此类的库代码,您将需要考虑对他们的影响。如果您认为它是安全的,您可以简单地添加返回类型,如通知中所示:
class Base {
public function getList(): Iterator {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
如果您需要支持旧版本的 PHP,或者尚未更新代码的用户,您可以暂时隐藏该通知:
class SubClass extends Base {
public function getList(): DirectoryIterator {
// ...
}
}
$foo = new SubClass;
var_dump($foo instanceOf Base); // true
var_dump($foo->getList() instanceOf Iterator); // true
Run Code Online (Sandbox Code Playgroud)
需要注意的是,内部返回类型可能会在 PHP 9.0 中强制执行,因此请确保您有一个可靠的计划来更改使用此属性标记的方法。
| 归档时间: |
|
| 查看次数: |
46718 次 |
| 最近记录: |