考虑:
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
上的 PHPStorm 之类的 IDE 中的代码预测将指示 null|IDataObject
的返回类型,并且...不会告诉我有关其作为 FooDataObject
实例的性质的任何有价值信息,除了 IDataObject
中定义的 可能。
但是,作为程序员,我可以确定地知道返回的对象要么为 null,要么是
FooDataObject
的实例。
是否有任何技巧可以通知 IDE 返回的类型可以是
FooDataObject
?
我尝试过的两个半生不熟的解决方案是:
toDataObject()
,并将返回类型扩展为null|IDataObject|FooDataObject
。这可以解锁 FooDataObject
的属性和方法来进行预测,但这意味着为了一个唯一、愚蠢的目的而重载一个方法——丑陋的开销。@method FooDataObject toDataObject()
。这更加精简和干净,但是,当然,@method
表示法似乎对多种返回类型的支持为零。尝试执行 @method null|FooDataObject toDataObject()
,PHPStorm(至少)只能识别第一种类型。因此任何提示或技巧将不胜感激。我是代码预测的坚持者,我想在这个应用程序中建立一种实践,使明天的编码变得更容易。
当我使用以下内容测试
@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());
编辑抱歉,我忘记了联合类型部分,但这也对我有用:
interface I{}
class Data implements I{}
abstract class P
{
public function getThing(): null|I
{
return null;
}
}
/**
* @method null|P getThing()
*/
class C extends P {
}