如何在不使用注释的情况下推断动态实例化 class 的类型?

How to infer type of a dynamically instantiated class without using annotations?

我有一个动态配置,我在其中定义了支持的 classes 供使用:

'registeredRequestParameters' => [
    SearchParameter::class,
    ReturnsParameter::class,
    OrderByParameter::class,
    RelationsParameter::class
],

所有这些 class 都扩展了一个摘要 class AbstractParameter

现在,当我在我正在开发的包中注册它们时,我正在这样做:

foreach ($this->requestParameters as $parameter) {
    /**
     * @var AbstractParameter $instance
     */
    $instance = new $parameter($this->request, $this->builder, $this->configModel);
    $instance->appendQuery();
}

这工作正常,但是我需要说 $instance 实际上是一个 AbstractParameter,否则我的 IDE 不会从那个 class.

有没有不用注释的方法?

使用类型 annotations 绝对没有错。这就是他们在那里的目的。

但我同意适当的类型提示更好更稳健。

但是为此你不能不使用动态实例化。改用抽象工厂。这将使代码更清晰、更灵活、更明确。

abstract class ParameterFactory {
    
    public static parameter($type, $request, $builder, $configModel) : AbstractParameter
    {
        
        switch ($type) {
            case SearchParameter::class:
                return new SearchParameter($request, $builder, $configModel);
            case ReturnsParameter::class:
                return new ReturnsParameter($request, $builder, $configModel);
            case OrderByParameter::class:
                return new OrderByParameter($request, $builder, $configModel);
            case RelationsParameter::class:
                return new OrderByParameter($request, $builder, $configModel);
        }

        throw new \InvalidArgumentException("Class $type not supported by factory");
            
    }
}

那么你会做:

foreach ($this->requestParameters as $parameter) {  
    $instance = ParameterFactory::parameter(parameter, $this->request, $this->builder, $this->configModel);
    $instance->appendQuery();
}

顺便说一句,我会为此创建一个 ParameterInterface 和类型提示,而不是抽象的 class。