这已经被反复询问,但回复有点旧,我有点绝望地希望有所改变,因为“无法完成”的回复。
上下文:
class AbstractBuildObject {}
class Hammer extends AbstractBuildObject{}
class Nail extends AbstractBuildObject{}
class AbstractFactory{
/**
* return $type
*/
public function build1(string $type): AbstractBuiltObject {
return new $type();
}
/**
* return any(AbstractBuiltObject)
*/
public function build2(string $someArg): AbstractBuiltObject {
$type = $this->decideTypeBasedOnArgsAndState($someArg);
return new $type();
}
}
我试图用构建器上方的注释来表示我需要的东西。
return $type
(或者理想情况下 return $type of AbstractBuiltObject
应该暗示在输入参数中指定了返回类型。
在第二种情况下,any(AbstractBuiltObject)
表示可能返回抽象类的任何派生实体。
所以我需要某种注解来实现我描述的效果。这些注释显然不起作用,我只是用它们来说明概念。
我知道有人可能会想使用像 return Hammer|Nail
这样的管道类型连接,但就我而言,每次向项目添加新的具体实现时都应该修改工厂类,这也不够具体在 build1
的情况下,我确切地知道返回类型应该是什么。
所以,简而言之,我需要它至少在 PhpStorm 中工作:
(new AbstractFactory())->build1(Hammer::class)-> // I should have Hammer autocomplete here
(new AbstractFactory())->build2('foo')-> // I should have autocomplete of any concretion of the abstract here
答案 0 :(得分:0)
关于打破 SOLID 中的 D 的哲学对话,如果您希望这样的事情自动完成仅在 Hammer
上可用的方法:
(new AbstractFactory())->build1(Hammer::class)->
那么您已经承诺专门为 Hammer
类编写此代码块。如果你打算这样做,那么你不妨这样做:
$hammer = (new AbstractFactory())->build1(Hammer::class);
如果你这样做,那么你也可以这样做:
/**
* @var Hammer
*/
$hammer = (new AbstractFactory())->build1(Hammer::class);
然后您在 $hammer->
上的自动完成应该可以工作。
答案 1 :(得分:0)
我们采用的解决方案是这样的:
<?php
class AbstractBuiltClass {
/**
* @return static
*/
public static function type(self $instance)
// change return type to :static when #PHP72 support is dropped and remove explicit typecheck
:self
{
if(!($instance instanceof static)){
throw new Exception();
}
return $instance;
}
}
class Hammer extends AbstractBuiltClass{
function hammerMethod(){}
}
Hammer::type($factory->get(Hammer::class))->hammerMethod();
可行解决方案的竞争者: