【问题标题】:static return type in PHP 7 interfacesPHP 7 接口中的静态返回类型
【发布时间】:2015-09-06 07:21:15
【问题描述】:

为什么在 PHP 7 中不能声明一个返回类型为 static 的接口?

假设我有以下课程:

interface BigNumber {
    /**
     * @param BigNumber $that
     *
     * @return static
     */
    public function plus(BigNumber $that);
}

class BigInteger implements BigNumber { ... }
class BigDecimal implements BigNumber { ... }

我想强制plus()方法的返回类型为static,即:

  • BigInteger::plus() 必须返回 BigInteger
  • BigDecimal::plus() 必须返回 BigDecimal

我可以通过以下方式声明接口:

public function plus(BigNumber $that) : BigNumber;

但这并不能强制执行上述内容。我想做的是:

public function plus(BigNumber $that) : static;

但到目前为止,PHP 7 对此并不满意:

PHP 解析错误:语法错误,意外的“静态”(T_STATIC)

这是否有特定原因,或者这是一个应该报告的错误?

【问题讨论】:

  • 类型不变性,这就是原因。实现/覆盖方法必须与 PHP 中的类型完全匹配; static 没有 - 显然,因为它指的是当前上下文,因此不能保持不变。

标签: php interface php-7


【解决方案1】:

2020 年更新

PHP 8 中的静态返回类型 have been introduced

【讨论】:

    【解决方案2】:

    这不是错误,只是从面向对象编程的角度来看,它在设计方面没有意义。

    如果您的BigIntegerBigDecimal 同时实现BigNumber,那么您关心他们履行的合同。我这种情况,是BigNumber的界面。

    因此,您应该在接口中使用的返回类型是BigNumber,因为任何针对该接口进行编码的人除了该接口的成员之外什么都不知道。如果您需要知道返回的是哪一个,则接口可能一开始就太宽了。

    注意:带有generics的编程语言可以通过将返回类型指定为泛型类型来达到这个效果,但是PHP没有泛型,近期可能不会有。

    【讨论】:

    • 我的想法是在输入上保持灵活(例如,您可以将BigIntegerBigDecimal 进行比较),但在输出上严格(在类上调用的任何方法都应该返回一个实例)同级)。也许这并不完全有意义,但至少 PHPdoc 允许这种用法(@return static)!
    • 嗯 PHPDoc 实际上对static phpdoc.org/docs/latest/references/phpdoc/types.html 一无所知,最接近的是self,在这种情况下与接口返回类型提示相同。
    • 奇怪,这个:phpdoc.org/docs/latest/guides/types.html 实际上记录了static:“使用此值的类的对象,如果继承它将代表子类。(参见后期静态绑定在PHP 手册)。”
    • 最初我认为self 作为返回类型与指定完整的类名略有不同——我认为它是返回与你完全相同的类实例的合同访问。然而,在类型声明的上下文中,self 似乎只是完整类名的简写。这似乎是一个不幸的设计决策,因为在方法体的上下文中 self 是对类本身的引用。
    • 我至少可以找到一种“合法”用法——我正在创建抽象模型类,并且我有 find 功能。如果假设有派生 AbstractModel 的 UserModel,我在 AbstractModel 中找到了逻辑。该逻辑取决于在 UserModel 中实现的某些东西(即 UserModel 名称)。现在,我不仅希望 UserModel::find() 返回 UserModel 的实例,我还需要一些 UserModel 定义的细节。这样一来,就没有合乎逻辑的方法让我们说 UserModel::find() 返回 PostModel 包含另一个抽象静态函数,该函数为适当的表配置抽象模型。
    猜你喜欢
    • 2016-12-28
    • 1970-01-01
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 2016-08-01
    • 1970-01-01
    • 2012-11-20
    • 1970-01-01
    相关资源
    最近更新 更多