PHP Psalm方法参数协变问题求解
PHP Psalm方法参数协变问题求解
嗨,各位大佬,我最近在PHP Psalm的类型校验上卡壳了,想请教下有没有合适的解法😅
先给大家说下我的场景:我定义了一个Node接口,还有一堆实现它的子类(比如TaskNode、ProjectNode);然后有个Handler接口,里面有个handleNode()方法,这个方法本质上只需要处理Node类型的实例就行,不关心具体是哪个子类。但现在我实现Handler的子类时,比如TaskHandler只想处理TaskNode,ProjectHandler只想处理ProjectNode,Psalm就会报类型不兼容的错误。
我把核心代码贴出来方便大家理解:
<?php interface Node {} class TaskNode implements Node {} class ProjectNode implements Node {} interface Handler { /** * @param Node $node */ public function handleNode(Node $node): void; } class TaskHandler implements Handler { /** * @param TaskNode $node */ public function handleNode(TaskNode $node): void {} } class ProjectHandler implements Handler { /** * @param ProjectNode $node */ public function handleNode(ProjectNode $node): void {} } $handlers = [new TaskHandler(), new ProjectHandler()]; foreach ($handlers as $handler) { $handler->handleNode(new TaskNode()); // 这里Psalm会报错,因为ProjectHandler的handleNode只接受ProjectNode }
我本来想找合适的@template参数组合来解决这个问题,但试了好几种都没成功。而且在实际项目里,不能直接把Handler接口里的@param改成TaskNode|ProjectNode这种联合类型——因为这类Node子类有很多,后续还会新增,要是每次都要去更新100+类似的方法注释,维护成本太高了,完全不现实。
有没有朋友遇到过类似的场景?能不能给我指点下,用什么Psalm注解或者类型技巧,既能让这个场景通过校验,又不用硬编码所有的Node子类类型?
备注:内容来源于stack exchange,提问作者Jan Sverre
相关产品推荐
相关产品推荐

