PHP7 中的可空返回类型

Posted

技术标签:

【中文标题】PHP7 中的可空返回类型【英文标题】:Nullable return types in PHP7 【发布时间】:2016-02-10 01:56:35 【问题描述】:

php 7 引入了return type declarations。这意味着我现在可以指示返回值是某个类、接口、数组、可调用或新可提示的标量类型之一,这对于函数参数是可能的。

function returnHello(): string 
    return 'hello';

通常情况下,值并不总是存在,您可能会返回某种类型的东西,或者返回 null。虽然您可以通过将参数的默认值设置为 null (DateTime $time = null) 来使参数为空,但似乎没有办法为返回类型执行此操作。确实是这样,还是我不知何故找不到该怎么做?这些不起作用:

function returnHello(): string? 
    return 'hello';


function returnHello(): string|null 
    return 'hello';

【问题讨论】:

PHP7 还不允许可空返回类型,但是有一个 RFC 旨在解决 PHP 7.1 here 中的这个问题。建议的符号将是function returnString(?string $stringNull) : ?string return $stringNull; 我现在已经通过在我的应用程序中滥用异常来模拟可空性。如果你也很傻,这可能有用:github.com/JeroenDeDauw/OhMyPhp/blob/master/src/… 也许使用 PHP7 Trowable 接口可能更有意义(具体来说,扩展 TypeError 另见nullable types on PHP7.1 【参考方案1】:

PHP 7.1 现在支持nullable return types。我链接到的第一个 RFC 就是他们使用的那个:

function nullOrString(int $foo) : ?string

    return $foo%2 ? "odd" : null;


旧答案:

因为我的评论实际上是对问题的回答:

PHP 7 尚不支持可为空的返回类型,但有an RFC 来解决这个问题,它旨在登陆 PHP 7.1。如果通过,语法将影响所有类型提示(返回类型和类型提示):

public function returnStringOrNull(?array $optionalArray) : ?string

    if ($optionalArray) 
        return implode(', ', $optionalArray);//string returned here
    
    return null;

还有a competing RFC 可以添加联合类型,它可以做同样的事情,但看起来会有所不同:

public function returnStringOrNull(array|null $optionalArray) : string|null

    if ($optionalArray) 
        return implode(', ', $optionalArray);//string returned here
    
    return null;

不过,现在你必须写:

public function returnStringOrNull( array $optionalArray = null)

    if ($optionalArray) 
        return implode(', ', $optionalArray);
    

或者只返回一个空字符串与返回类型一致,并检查falsy值:

public function returnStringOrNull( array $optionalArray = null) : string

    if ($optionalArray) 
        return implode(', ', $optionalArray);
    
    return '';

//call
$string = $x->returnStringOrNull();
if (!$string) 
    $string = $x->returnStringOrNull(range(1, 10));

【讨论】:

PHP 7 won't support nullable return-types just yet, but there's an RFC out to address just that - 是的,RFC,“刚刚”。不要误会我的意思——我真的是 PHP 的重度用户,因为 真的很糟糕 PHP3 次到现在,没有差距,但是当我看到所有这些 RFC 被他们拒绝 7 次时,我的印象只是“WTF? !”。用户看到混乱并愿意以向后兼容的方式清理它,他们只会得到“不”。清洁方法命名混乱?固定null 不是太特殊的公民?不,不需要。添加 option 以使所有内容区分大小写?不……然后,令人惊讶的是人们会转换。 @MarcinOrlowski:可以为空的返回类型提示是有意义的。我遵循了几个 7 的 RFC,我在很大程度上同意他们拒绝了很多。他们关注的变化不是语言,而是运行时和编译器。对于一些被拒绝的 RFC,值得阅读讨论线程以了解他们选择不实施这些更改的原因(例如弃用 var)。可惜的是,他们确实接受了太多的好东西(例如宇宙飞船操作员) @EliasVanOotegem Nullable 类型现在得到适当支持,因为 7.1 于 12 月 1 日发布。 @lonesomeday:确实如此,在我的答案底部添加了链接+基本示例 嗯是更新这个答案的好类型!即 PHP 7.1 似乎不支持联合类型【参考方案2】:

Nullable Types 在 PHP 7.1 中可用。

这是一个语法示例:

public function getName(): ?string

    return $this->name; // name can be null

PHP 7.1 现在是 GA,您可以从 PHP 7.0 升级(只有少数向后不兼容的 changes 需要检查)

【讨论】:

IMO 在不实现“可为空”的情况下提供返回类型声明是一个笑话。在实现“可空”功能之前,返回类型不可用。 @joonas.fi IMO 严格类型的返回值应始终属于该类型,空返回不符合该合同,而应抛出异常,为空值的原因提供更多意义. @SteveBuzonas 如果您考虑在代表 Person 的对象上使用 getAgeInYears() 方法,您将如何为没有告诉我们他/她年龄的人建模?返回空?返回 0?返回 null 在语义上意味着“我们不知道”,而 0 在语义上意味着“这个人是 0 岁”。因此,我认为 getAgeInYears(): ?int 是最好的设计。抛出异常应该留给......异常情况。在大多数系统中不知道一个人的年龄不应被视为例外情况。 @joonas.fi 非常正确,这是一种常见的做法。但是,您的实现现在需要知道该字段可以为空并相应地显式处理。 x except when null 可以很好地做到这一点,这可以很容易地用 try/catch 来实现。此外,如果实际上需要该可为空字段中的值才能继续执行,则异常可能是更好的选择。 我注意到这种语法会导致 PHPMD 抛出很多错误。希望他们尽快修复它。【参考方案3】:

它适用于任何类型。 示例:

public function getOpportunity(): ?Opportunity

    return $this->opportunity;

【讨论】:

以上是关于PHP7 中的可空返回类型的主要内容,如果未能解决你的问题,请参考以下文章

具有泛型返回类型的可空引用类型

匹配参数的可空性和返回类型的泛型类型参数

C# 8中的可空引用类型

c# 中的可空类型是啥?

Java 8中的Optional 类型与 Kotlin 中的可空类型

kotlin 注释处理器中的可空类型