Chr*_*ris 23 php type-hinting php-8
我可以使用类型提示允许两种不同的类型吗?例如,参数1可以是2个类
function log (User|File $requester) {
}
Run Code Online (Sandbox Code Playgroud)
yiv*_*ivi 61
该提案已以 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
在学术上,这被称为类型联盟.
您可以通过创建接口,父类型等来作弊,如其他答案中所述,但除了为项目添加复杂性和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)
2015年2月14日,针对PHP 7.1提出了Union Types PHP RFC.在经过讨论和投票后,它被拒绝,18"否"反对11"是".
如果RFC已经被接受,那么PHP将具有与你所示的方式完全一致的联合类型(User|File).
该RFC有一些缺陷,但它为什么被拒绝的主要原因是,mainteners选民相当电阻变化特别是当它是关于类型的严格和其他编程范例(例如:"为什么我们需要的时候默认通吃型工会值"和"的类型对性能不利").
ish*_*egg 10
它目前在PHP中是不可能的.但是你可以有一个interface,并实现它User和File,然后使用该接口类型提示中log():
<?php
interface UserFile {
}
class User implements UserFile {
}
class File implements UserFile {
}
// snip
public function log (UserFile $requester) {
}
Run Code Online (Sandbox Code Playgroud)
您可以检查函数内部的类型。
function log ($requester) {
if ($requester instanceof User || $requester instanceof File) {
//Do your job
}
}
Run Code Online (Sandbox Code Playgroud)