当前位置: 首页 > 知识库问答 >
问题:

如何在泛型和继承中使用方法?

琴正初
2023-03-14

具有以下类别:

public interface Step<C extends Config> {
  void setConfig(C config);
}

public class ValidationStep implements Step<ValidationConf> {
  public void setConfig(ValidationConf conf) {}
  // implementation
}

public class ProcessStep implements Step<ProcessConf> {
  public void setConfig(ProcessConf conf) {}
  // implementation
}

public interface Config {
  Class<? extends Step> type();
}

public class ValidationConf implements Config {
  public Class<? extends Step> type() {
    return ValidationStep.class;
  }
}

public class ProcessConf implements Config {
  public Class<? extends Step> type() {
    return ProcessStep.class;
  }
}

因此,应用程序需要动态实例化步骤子类对象,相应地设置配置并运行步骤,如下所示。

List<Config> configs = loadConfigsFromRepository(); // contain all subtypes of Config
for (Config conf: configs) {
  Step<? extends Config> step = conf.type().getDeclaredConstructor().newInstance();

  step.setConfig(conf); // compiler complains

}

错误消息:

"方法setConfig(捕获#8-of?扩展Config)在类型Step中

查看文档,在这种情况下,Java看起来不友好:https://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html

克服此代码限制的可能解决方案是什么。setConfig(conf)

编辑[解决方案]

可在此处查看代码:https://github.com/danieldestro/cucumber-salad/tree/generics/src/main/java/my/generics

共有3个答案

谷良弼
2023-03-14

你的方法不完全正确。我建议您在真正需要反射之前不要使用反射。

注意,所有这些实现都应该隐藏在包中,只有Step接口应该是publicConfig实现保存所有数据以创建Step类,所以只需将其委托给它。

package steps

public interface Step<C extends Config> {
  void run(Context context);
}

private final class ValidationStep implements Step<ValidationConf> {
    private final ValidationConf config;
    
    public ValidationStep(ValidationConf config) {
        this.config = config;
    }
}

private class ProcessStep implements Step<ProcessConf> {
    private final ProcessConf config;
    
    public ValidationStep(ProcessConf config) {
        this.config = config;
    }    
}

public interface Config {
    
    Step<? extends Config> createStep();
  
}

private class ValidationConf implements Config {
    
    public Step<ValidationConf> createStep() {
        return new ValidationStep(this);
    }
}

private class ProcessConf implements Config {
    public Step<ValidationConf> createStep() {
        return new ProcessConf(this);
    }
}

package foo

List<Config> configs = loadConfigsFromRepository();

for (Config config : loadConfigsFromRepository()) {
  config.createStep().run(context);
}
赵英范
2023-03-14

去掉通配符。你不需要它。

Step<Config> step = (Step<Config>) conf.type().getDeclaredConstructor().newInstance();
水焱
2023-03-14

因为<代码>步骤。setConfig(Config)是一个“消费者”,解决“code>不适用于参数(Config)的一种方法是“您得到的错误是使用我在这里演示的下限…”…

…  
List< ? extends Config > configs = loadConfigsFromRepository( ); // contain all subtypes of Config
  
for ( Config conf: configs ) {
    Step< ? super Config > step = conf.type( ).getDeclaredConstructor( ).newInstance( );

      step.setConfig( conf ); // *set* makes Step a „consumer“
}
…

这样你就不需要另一个答案提出的演员阵容。

我的loadConfigsFromRepository()实现如下…

static List< ? extends Config > loadConfigsFromRepository(){ 
    
    return of( new ValidationConf( ), new ProcessConf( ) );        
}
 类似资料:
  • 问题内容: 我有三节课: 现在在我的主要职能中,我做这样的事情: 但这会产生2个编译时错误: 无法将A转换为fileHandler 无法将B转换为fileHandler 如果基类不是泛型的,那么我如何摆脱这些错误呢? 更新: 我的班级层次结构是: 调用函数的C类或 调用函数的D类。 C和D都从抽象类E派生。 现在,我应该如何在C和D以及E中定义这些功能: 我给出了以下内容: E: C: D: C,

  • 为了在 .NET Core 中使用依赖关系注入,我们构建了一堆存储库接口,供控制器用于数据库交互。 我们有一个< code>EntityBase类,其中包含一些方法,我们的通用存储库接口使用这个基类,例如:< code>IRepository 我想添加一个更具体的 类,该类扩展了 ,以表示我们有一些要按标记筛选的实体。我希望 有一个抽象属性,我可以在控制器中使用该属性,以便我可以抽象出来并重用过滤

  • 我有一个典型的问题,什么是更好的,我认为答案总是视情况而定,但我还是想澄清一下。所以有两种方法: 逻辑是: 我知道由于类型擦除,方法签名存在冲突,所以我的问题不是“为什么我不能同时拥有这两个方法?”,而是“你会选择哪种方法?”。

  • 和这个问题相关的课程: 现在,这似乎已被编译器接受。不幸的是,我不知道/理解如何创建的新实例,。 当然,这确实不起作用:

  • 问题内容: 我正在编写一个流畅的API,以配置和实例化一系列“消息”对象。我有消息类型的层次结构。 为了在使用Fluent API时能够访问子类的方法,我使用了泛型来对子类进行参数化,并使所有的fluent方法(以“ with”开头)都返回泛型类型。注意,我省略了流利方法的大部分内容。其中进行了许多配置。 具体的子类类似地重新定义泛型。 该代码有效,即,我可以实例化任何类并使用所有流利的方法: 以

  • 我有一个典型的问题,什么是更好的,我认为答案总是视情况而定,但我还是想澄清一下。所以有两种方法: 逻辑是: 我知道由于类型擦除,方法签名存在冲突,所以我的问题不是“为什么我不能同时拥有这两个方法?”,而是“你会选择哪种方法?”。