PHP:如何让IDE识别子类toDataObject方法的实际返回类型?
让IDE识别Model子类
toDataObject方法的具体返回类型 先看现有代码:
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();
当前问题:IDE会把$do的类型推断为null|IDataObject,但实际返回值是null|FooDataObject,无法触发IDE针对FooDataObject的属性、方法提示。
试过的两种不理想方案:
- 在子类中重写
toDataObject()方法,扩展返回类型为null|IDataObject|FooDataObject,但会产生冗余代码。 - 在子类PHPDoc中添加
@method FooDataObject toDataObject(),但@method不支持多返回类型,写@method null|FooDataObject toDataObject()时,PHPStorm只会识别第一个类型。
推荐解决方案
方案1:利用PHP原生泛型(PHP 7.4+)
修改抽象类,引入泛型参数并绑定到IDataObject,让子类继承时指定具体的DataObject类型:
interface IDataObject { public static function from(BaseModel $model): ?self; } // 定义泛型抽象类,T绑定到IDataObject abstract class BaseModel<T extends IDataObject> { protected static string $dataObjectClass; public function toDataObject(): ?T { return static::$dataObjectClass::from($this); } } // 子类继承时指定泛型参数为FooDataObject class FooModel extends BaseModel<FooDataObject> { protected static string $dataObjectClass = FooDataObject::class; } class FooDataObject implements IDataObject { public static function from(BaseModel $model): ?self { // 实现转换逻辑 return new self(); } } $do = (new FooModel)->toDataObject();
此时IDE会正确推断$do的类型为null|FooDataObject,无需冗余代码,原生语法支持。
方案2:利用PHPDoc泛型提示(兼容低版本PHP)
如果项目使用的PHP版本不支持原生泛型,可以通过PHPDoc标记让IDE识别:
interface IDataObject { /** * @param BaseModel $model * @return ?self */ public static function from(BaseModel $model): ?self; } /** * @template T of IDataObject */ abstract class BaseModel { /** @var class-string<T> */ protected static string $dataObjectClass; /** * @return ?T */ public function toDataObject(): ?IDataObject { return static::$dataObjectClass::from($this); } } /** * @extends BaseModel<FooDataObject> */ class FooModel extends BaseModel { protected static string $dataObjectClass = FooDataObject::class; } class FooDataObject implements IDataObject { /** * @param BaseModel $model * @return ?self */ public static function from(BaseModel $model): ?self { // 实现转换逻辑 return new self(); } } $do = (new FooModel)->toDataObject();
通过@template定义泛型参数,@extends在子类中指定具体类型,IDE同样能正确推断$do为null|FooDataObject,兼容PHP 7.3及以下版本。
内容的提问来源于stack exchange,提问作者Rikaelus
相关产品推荐
相关产品推荐

