PHPStan中@return T与@return Aclass为何报错情况不同?
PHPStan泛型注解报错原因及解决方法
问题根源
你用@template T of Aclass+@return T的泛型注解时,PHPStan报错的核心原因是:你的注解承诺了方法返回的实例类型,必须和传入的$param类名完全匹配,但实际代码里不管传什么参数都固定返回Bclass实例,这违反了泛型约束的约定。
两种注解的本质区别
@return Aclass:只是声明方法返回Aclass或它的任意子类,只要返回值是Aclass的子类就合法,不要求和传入参数对应。所以你返回固定的Bclass时,PHPStan不会报错。@template T of Aclass + @return T:这是泛型约束,它的意思是:调用方法时传入哪个Aclass子类的类名,方法就必须返回该子类的实例。比如传入Cclass::class,就必须返回Cclass实例,而你现在硬返回Bclass,和泛型承诺的类型不匹配,所以PHPStan会报错。
解决方法
根据你的实际需求选一种:
1. 让工厂真正根据传入参数创建对应实例(符合泛型注解)
修改代码,让方法根据传入的类名实例化对象,这样就满足泛型约束:
abstract class Aclass {} final class Bclass extends Aclass {} final class Cclass extends Aclass {} final class Factory { /** * @template T of Aclass * @param class-string<T> $param * @return T */ public function create($param) { return new $param(); } }
2. 固定返回Bclass(不使用泛型)
如果你确实只能返回Bclass,那泛型注解就不合适,直接声明返回具体类型更准确:
abstract class Aclass {} final class Bclass extends Aclass {} final class Cclass extends Aclass {} final class Factory { /** * @param class-string<Aclass> $param * @return Bclass */ public function create($param) { // some kind of factory logic return new Bclass(); } }
或者保持原来的@return Aclass也可以,只是类型精度稍低。
内容的提问来源于stack exchange,提问作者Slava Basko
相关产品推荐
相关产品推荐

