我有一些方法可以返回两种返回类型之一 - (我正在使用一个利用MCV的框架,所以特别重构这几个函数并不吸引人)
是否可以声明返回类型返回一个或另一个而失败?
function test(): ?
{
if ($this->condition === false) {
return FailObject;
}
return SucceedObject;
}
答案 0 :(得分:63)
截至目前,支持的方式是两个对象共享一个接口。例如:
interface ReturnInterface {}
class FailObject implements ReturnInterface {}
class SuccessObject implements ReturnInterface {}
function test(): ReturnInterface {}
在此示例中,ReturnInterface
为空。它仅仅存在支持所需的返回类型声明。
警告强>:
以下讨论的RFC(联盟类型)已被拒绝 https://wiki.php.net/rfc/union_types
有关几种竞争RFC的联合类型的热烈讨论。如果其中任何一个通过,那么建议的签名将是:
function test(): FailObject|SuccessObject {}
那就是说,无论联合类型如何,我更喜欢接口方法。对我而言,它更清晰,更具可扩展性。如果我以后想要WarnObject
我只需要将其定义为扩展ReturnInterface
- 而不是浏览所有签名并将其更新为FailObject|SuccessObject|WarnObject
。
答案 1 :(得分:30)
正如bishop所说,有一个用于添加多种返回类型的RFC。但是,我想我在PHP7.1中添加了你现在可以指定一个可以为空的返回类型:
function exampleFunction(string $input) : ?int
{
// Do something
}
所以这个函数会接受一个字符串,并在int之前添加问号,你允许它返回null或整数。
这是指向文档的链接: http://php.net/manual/en/functions.returning-values.php
以下是该页面的引用解释用法: PHP 7.1允许使用类型声明前面的void和null返回类型。 - (例如,函数canReturnNullorString():? string)
此外,这是与此相关的另一个主题:Nullable return types in PHP7
答案 2 :(得分:16)
PHP 7.2现在支持对象返回类型
http://php.net/manual/en/migration72.new-features.php
function test(object $obj) : object
// return any type of object ...
答案 3 :(得分:2)
PHP 8.0于2020年发布时,this will be possible。
您将能够使用联合类型来指定以下内容:
function test(): SucceedObject|FailObject
{
if ($this->condition === false) {
return FailObject;
}
return SucceedObject;
}
这是可能的事实并不意味着它总是可取的。在很多(可能是大多数)情况下,使用接口(例如Result
和Fail
都将实现的接口(例如Succeed
)仍然是可取的。
但是在其他情况下,联合类型也可以替代弱类型。例如。既接受string
也接受int
的方法,或者描述返回stropos()
的函数int|false
的返回类型。
答案 4 :(得分:-1)
这不是正确的方法:
function test(): ?
{
if ($this->condition === false) {
return FailObject;
}
return SucceedObject;
}
多种返回类型是一种不好的做法。好的做法:
您应该定义一个例外:
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
}