php类型提示我可以允许两种类型吗?

Chr*_*ris 23 php type-hinting php-8

我可以使用类型提示允许两种不同的类型吗?例如,参数1可以是2个类

function log (User|File $requester) {

}
Run Code Online (Sandbox Code Playgroud)

yiv*_*ivi 61

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

提案已以 61 票赞成、5 票反对票通过,实施准备就绪。

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

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

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

这意味着F::foo()期望 aFile或资源,并将返回 anint或 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 { /** **/ }
}
Run Code Online (Sandbox Code Playgroud)

但这不是:

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


Mor*_*ing 28

在学术上,这被称为类型联盟.

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)
{
Run Code Online (Sandbox Code Playgroud)

这至少会为自动完成和静态代码分析带来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 ...
}
Run Code Online (Sandbox Code Playgroud)

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

2015年2月14日,针对PHP 7.1提出了Union Types PHP RFC.在经过讨论和投票后,它被拒绝,18"否"反对11"是".

如果RFC已经被接受,那么PHP将具有与你所示的方式完全一致的联合类型(User|File).

该RFC有一些缺陷,但它为什么被拒绝的主要原因是,mainteners选民相当电阻变化特别是当它是关于类型的严格和其他编程范例(例如:"为什么我们需要的时候默认通吃型工会值""的类型对性能不利").

  • 我有点不相信这一点,但是我只是检查了一下,可悲的是去看看RFC来思考它,然后决定去看一下RFC索引,而UNION TYPES V2则是最重要的RFC清单。哇。它实际上是在6天前开始讨论的。https://github.com/php/php-rfcs/pull/1-这也是GH上讨论的第一个RFC。迷人的时机哈哈 (4认同)
  • 联合类型的 [RFC](https://wiki.php.net/rfc/union_types_v2) 在 PHP 8 中被接受并实现。 (2认同)

ish*_*egg 10

它目前在PHP中是不可能的.但是你可以有一个interface,并实现它UserFile,然后使用该接口类型提示中log():

<?php
interface UserFile {
}

class User implements UserFile {
}
class File implements UserFile {
}

// snip

public function log (UserFile $requester) {
}
Run Code Online (Sandbox Code Playgroud)


til*_*z0R 6

您可以检查函数内部的类型。

function log ($requester) {
    if ($requester instanceof User || $requester instanceof File) {
        //Do your job
    }
}
Run Code Online (Sandbox Code Playgroud)