是否可以在 PHP 7 上指定多个 return 类型?
Is it possible to specify multiple return types on PHP 7?
我有一些方法可以 return 两种 return 类型之一 。我正在使用一个利用 MCV 的框架,因此重构这几个函数特别没有吸引力。
是否可以声明 return 类型 return 一个或另一个并在其他任何事情上失败?
function test(): ?
{
if ($this->condition === false) {
return FailObject;
}
return SucceedObject;
}
从 PHP 8+ 开始,您可以使用 union types:
function test(): FailObject|SuccessObject {}
自 PHP 4 以来的所有版本中都可用的另一种方法是让两个对象共享一个接口。示例:
interface ReturnInterface {}
class FailObject implements ReturnInterface {}
class SuccessObject implements ReturnInterface {}
function test(): ReturnInterface {}
在此示例中,ReturnInterface
为空。它的存在本身就支持所需的 return 类型声明。
您也可以使用基础,可能是抽象的,class。
对我来说,对于这个用例,接口比联合类型更清晰、更可扩展。例如,如果我以后想要一个 WarnObject
,我只需要将它定义为扩展 ReturnInterface
—— 而不是遍历所有签名并将它们更新为 FailObject|SuccessObject|WarnObject
.
正如 bishop 所指出的,有一个用于添加多个 return 类型的 RFC。但是,我想我会补充说,从 PHP7.1 开始,您现在可以像这样指定可为 null 的 return 类型:
function exampleFunction(string $input) : ?int
{
// Do something
}
所以这个函数将接受一个字符串,并通过在 int 之前添加问号,您允许它 return 为 null 或整数。
这是文档的 link:
http://php.net/manual/en/functions.returning-values.php
这是该页面上解释用法的引述:
PHP 7.1 通过在类型声明前加上 ? 来允许 void 和 null return 类型。 —(例如函数 canReturnNullorString(): ?string)
此外,还有一个与此相关的话题:
PHP 从 7.2 开始支持对象 return 类型
http://php.net/manual/en/migration72.new-features.php
function test(object $obj) : object
// return any type of object ...
这不是正确的方法:
function test(): ?
{
if ($this->condition === false) {
return FailObject;
}
return SucceedObject;
}
多个 return 类型是不好的做法。 好的做法:
你应该定义一个例外:
class FailObjectException extends \Exception
{
private $exampleExtraInfo;
public function __construct($exampleExtraInfo, $message)
{
parent::__construct($message);
$this->exampleExtraInfo = $exampleExtraInfo;
}
public function exampleExtraInfo(): int
{
return $this->exampleExtraInfo;
}
}
现在,您可以像这样定义函数:
function test(): SucceedObject
{
if ($this->condition === false) {
throw new FailObjectException(...,...);
}
return SucceedObject;
}
并将此函数与 try/catch 一起使用:
try{
$succeedObject = $any->test();
} catch (FailObjectException $exception){
//do something
}
因为 PHP 8.0 this is possible.
您现在可以使用联合类型来指定:
function test(): Success|Failure
{
if ($this->condition === false) {
return new Failure();
}
return new Success();
}
事实上这是可能的并不意味着它总是可取的。在许多(可能是大多数)情况下,按照不同答案中的建议使用接口(例如 Result
,Failure
和 Failure
都将实现)仍然更可取。
但在其他情况下,联合类型可以作为弱类型的替代方案。例如。接受 string
和 int
的方法,或者描述函数的 return 类型,如 stripos()
,其中 returns int|false
。
我有一些方法可以 return 两种 return 类型之一 。我正在使用一个利用 MCV 的框架,因此重构这几个函数特别没有吸引力。
是否可以声明 return 类型 return 一个或另一个并在其他任何事情上失败?
function test(): ?
{
if ($this->condition === false) {
return FailObject;
}
return SucceedObject;
}
从 PHP 8+ 开始,您可以使用 union types:
function test(): FailObject|SuccessObject {}
自 PHP 4 以来的所有版本中都可用的另一种方法是让两个对象共享一个接口。示例:
interface ReturnInterface {}
class FailObject implements ReturnInterface {}
class SuccessObject implements ReturnInterface {}
function test(): ReturnInterface {}
在此示例中,ReturnInterface
为空。它的存在本身就支持所需的 return 类型声明。
您也可以使用基础,可能是抽象的,class。
对我来说,对于这个用例,接口比联合类型更清晰、更可扩展。例如,如果我以后想要一个 WarnObject
,我只需要将它定义为扩展 ReturnInterface
—— 而不是遍历所有签名并将它们更新为 FailObject|SuccessObject|WarnObject
.
正如 bishop 所指出的,有一个用于添加多个 return 类型的 RFC。但是,我想我会补充说,从 PHP7.1 开始,您现在可以像这样指定可为 null 的 return 类型:
function exampleFunction(string $input) : ?int
{
// Do something
}
所以这个函数将接受一个字符串,并通过在 int 之前添加问号,您允许它 return 为 null 或整数。
这是文档的 link: http://php.net/manual/en/functions.returning-values.php
这是该页面上解释用法的引述: PHP 7.1 通过在类型声明前加上 ? 来允许 void 和 null return 类型。 —(例如函数 canReturnNullorString(): ?string)
此外,还有一个与此相关的话题:
PHP 从 7.2 开始支持对象 return 类型
http://php.net/manual/en/migration72.new-features.php
function test(object $obj) : object
// return any type of object ...
这不是正确的方法:
function test(): ?
{
if ($this->condition === false) {
return FailObject;
}
return SucceedObject;
}
多个 return 类型是不好的做法。 好的做法:
你应该定义一个例外:
class FailObjectException extends \Exception
{
private $exampleExtraInfo;
public function __construct($exampleExtraInfo, $message)
{
parent::__construct($message);
$this->exampleExtraInfo = $exampleExtraInfo;
}
public function exampleExtraInfo(): int
{
return $this->exampleExtraInfo;
}
}
现在,您可以像这样定义函数:
function test(): SucceedObject
{
if ($this->condition === false) {
throw new FailObjectException(...,...);
}
return SucceedObject;
}
并将此函数与 try/catch 一起使用:
try{
$succeedObject = $any->test();
} catch (FailObjectException $exception){
//do something
}
因为 PHP 8.0 this is possible.
您现在可以使用联合类型来指定:
function test(): Success|Failure
{
if ($this->condition === false) {
return new Failure();
}
return new Success();
}
事实上这是可能的并不意味着它总是可取的。在许多(可能是大多数)情况下,按照不同答案中的建议使用接口(例如 Result
,Failure
和 Failure
都将实现)仍然更可取。
但在其他情况下,联合类型可以作为弱类型的替代方案。例如。接受 string
和 int
的方法,或者描述函数的 return 类型,如 stripos()
,其中 returns int|false
。