是否可以键入不止一种类型的提示?

新手上路,请多包涵

我可以使用类型提示允许两种不同的类型吗?

例如参数 $requester 可以是 UserFile

 function log (User|File $requester) {

}

原文由 Chris 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 345
2 个回答

在学术上,这称为 类型联合

PHP 中的联合类型

您可以通过创建接口、父类型等来作弊,如其他答案中所述,但除了为您的项目增加复杂性和 LoC 之外,还有什么意义呢?另外,这不适用于标量类型,因为您无法扩展/实现标量类型。

您不会使代码更具可读性,反而会适得其反。除非那些类/接口已经存在并且它们是因为 OOP 而存在于此,而不是为了解决类型提示问题。

解决方法

PHP 中的规范答案是……好吧,只是不要放置类型提示。该语言不被认为具有复杂而强大的类型系统,并且试图解决该语言的缺陷并不是一个好的答案。

相反,正确记录您的功能:

 /**
 * Description of what the function does.
 *
 * @param User|File $multiTypeArgument Description of the argument.
 *
 * @return string[] Description of the function's return value.
 */
function myFunction($multiTypeArgument)
{

这至少会带来 IDE 对自动完成和静态代码分析的支持。在私人项目、网站等上工作时就足够了。

在设计公共 API(PHP 库等)时,有时您可能希望对 API 使用者的输入更具防御性。

那么@tilz0R 的答案就是要走的路:

 function log($message) {
    if (!is_string($message) && !$message instanceof Message) {
        throw new \InvalidArgumentException('$message must be a string or a Message object.');
    }

    // code ...
}

PHP(几乎)拥有联合类型的那一天

2015 年 2 月 14 日, 联合类型 PHP RFC 被提议用于 PHP 7.1。经过讨论和表决,18票否决11票否决。

如果 RFC 已被接受,PHP 的联合类型将与您显示的方式完全相同( User|File )。

RFC 有一些缺陷,但它被拒绝的主要原因是维护者投票者非常抵制改变,尤其是当它涉及类型严格性和其他编程范例时(例如, “为什么我们需要类型联合,而默认情况下会全部采用值类型”“这对性能不利” )。

原文由 Morgan Touverey Quilling 发布,翻译遵循 CC BY-SA 3.0 许可协议

从 PHP 8.0 开始, 这将通过 包含联合类型成为可能。

提案已获得 61 票赞成、5 票反对的投票 结果,实施工作已准备就绪。

之前有一个 RFC 提出这个建议,在另一个答案中提到,但那个最终被拒绝了。

它将完全按照您问题中的示例工作:

 class F
{
   public function foo (File|Resource $f) : int|float { /** implement this**// }
}

Which means that F::foo() expects either a File or a resource, and will return an int or a float .

补充几点:

可空性

此外,您可以使用 null 声明联合。 A|null 等同于 ?A ,但更复杂的声明 A|B|null 也是可能的。

“假”伪类型

也可以使用 false 类型作为联合类型声明的一部分。例如 int|false 。这主要是由于历史原因,因为一些内部函数在某些类型的错误条件下返回 false 。以 strpos() 为例。

在这些情况下,更现代的函数可能应该返回 null 或抛出异常,但包含此替代方案是为了解决遗留代码。

在继承中添加和删除联合类型的一部分

为参数类型提示 添加 联合类型是合法的(因此,使函数的限制更少),并为返回类型提示 删除 联合类型(使返回类型更具体)。

从上面给定类 F ,这是合法的:

 class G extends F
{
    public function foo(File|Resource|string $f) : int { /** **/ }
}

但这不是:

 class H extends F
{
    public function foo(File $f) : int|float|bool { /** **/ }
}

原文由 yivi 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏