PHP -用于代码预测的欺骗返回类型协方差

tvmytwxo  于 11个月前  发布在  PHP
关注(0)|答案(1)|浏览(71)

请考虑:

abstract class BaseModel {
    protected static string $dataObjectClass;

    public function toDataObject(): ?IDataObject
    {
        return static::$dataObjectClass::from($this);
    }
}

class FooModel extends BaseModel {
    protected static string $dataObjectClass = FooDataObject::class;
}

$do = (new FooModel)->toDataObject();

字符串
$do上的PHP Storm等IDE中的代码预测将指示返回类型null|IDataObject和...没有告诉我任何关于它作为FooDataObject示例的本质的有价值的东西,除了IDataObject中可能定义的东西。
然而,作为程序员,我可以肯定地知道返回的对象要么是null,要么是FooDataObject的示例。
有没有什么技巧可以通知IDE返回的类型可以是FooDataObject
我尝试过的两个半生不熟的、蹩脚的解决方案是:
1.重写子类中的toDataObject()并将返回类型扩展为null|IDataObject|FooDataObject。这可以解锁FooDataObject的属性和方法以进行预测,但这意味着重载一个方法,只有一个愚蠢的目的--丑陋的开销。
1.在phpdoc子类中包含@method FooDataObject toDataObject()。这是更精简和更清晰的,但是,当然,@method表示法似乎对多个返回类型没有任何支持。尝试做@method null|FooDataObject toDataObject()和PHPStorm(至少)只识别第一种类型。
所以任何提示或技巧都将不胜感激。我坚持代码预测,我希望在这个应用程序中建立一个实践,使明天的编码更容易。

6bc51xsx

6bc51xsx1#

当我使用以下代码测试@method时,我确实从PhpStorm获得了自动完成:

interface I{}
class Data implements I{}

abstract class P
{
    public function getThing(): ?I
    {
        return null;
    }
}

/**
 * @method Data getThing()
 */
class C extends P {}

(new C)->getThing();

字符串


的数据
正如你提到的,重写方法只改变返回类型确实会增加冗余,但是你也可以得到运行时类型检查,这可能对你有利,也可能不利,特别是因为你可以显式地从返回中删除null的可能性。

interface I{}
class Data implements I{}

abstract class P
{
    public function getThing(): ?I
    {
        return null;
    }
}

class C extends P {
    public function getThing(): Data
    {
        return new Data;
    }
}

var_dump((new C)->getThing());


演示:https://3v4l.org/hdscV

编辑抱歉,我忘记了工会类型部分,但这也为我工作:

interface I{}
class Data implements I{}

abstract class P
{
    public function getThing(): null|I
    {
        return null;
    }
}

/**
 * @method null|P getThing()
 */
class C extends P {
}


相关问题