我有一个如下所示的类和接口:

interface Employee {...}

class Developer implements Employee {...}

然后我有实现入职流程中的步骤的类:

interface OnboardingStep<T extends Employee> {
  void perform(T newEmployee);
}

class GeneralOnboardingStep implements OnboardingStep<Employee> {
  GeneralOnboardingStep() {}

  @Override
  void perform(Employee newEmployee) {...}
}

class DeveloperOnboardingStep implements OnboardingStep<Developer> {
  DeveloperOnboardingStep() {}

  @Override
  void perform(Developer newDeveloper) {...}
}

完整的入职流程包括一般入职加上针对开发人员的特定入职.

所以我想做的是:

abstract class OnboardingProcess<T extends Employee> {

  // This is where I need help, see below
  private final List<OnboardingStep<T>> onboardingSteps;

  protected OnboardingProcess(List<OnboardingStep<T>> onboardingSteps) {
    this.onboardingSteps = onboardingSteps;
  }

  public void perform(T newEmployee) {
    for (var onboardingStep: onboardingSteps) {
      onboardingStep.perform(newEmployee);
  }
}

class DeveloperOnboardingProcess extends OnboardingProcess<Developer> {

  DeveloperOnboardingProcess() {
    // This does not work
    super(List.of(
      new GeneralOnboardingStep(),
      new DeveloperOnboardingStep()
    ));
  }
}

这不起作用,因为DeveloperOnboardingProcess中的列表可能只包含OnboardingStep<Developer>,而不是OnboardingStep<Employee>.

但它应该是可行的,因为Developer实现了Employee.(我说的"应该奏效"的意思是:"我希望它奏效了").

我如何调整抽象类中的列表类型,使其也接受接口的加载步骤?

推荐答案

您可能需要的是以下内容(但请参见下面的内容):

private final List<OnboardingStep<? super T>> onboardingSteps;

protected OnboardingProcess(List<OnboardingStep<? super T>> onboardingSteps) {
    this.onboardingSteps = onboardingSteps;
}

? super T意味着每个列表元素的perform方法保证接受T实例,因为它将把构造函数参数限制为类型为T或T的超类的步骤.因此,对于DeveloperOnboardingProcess,构造函数可以采用OnboardingStep<Developer>或OnboardStep的列表元素,其泛型类型是Developer的任何超类,包括Employee本身.

然而,有一件事你不能做,那就是通过List<DeveloperOnboardingStep>分.List<DeveloperOnboardingStep>等同于List<OnboardingStep<Developer>>List<OnboardingStep<Employee>>,因为后者有一个add(和addAll等)方法,它允许OnboardingStep、DeveloperOnboardinStep或OnboardingStep的任何其他future 的子类,而List<DeveloperOnboardingStep>有一个add方法,它只接受DeveloperOnboardingStep参数.

比方说,要允许List<DeveloperOnboardingStep>个参数,请使用以下命令:

private final List<? extends OnboardingStep<? super T>> onboardingSteps;

protected OnboardingProcess(List<? extends OnboardingStep<? super T>> onboardingSteps) {
    this.onboardingSteps = onboardingSteps;
}

Java相关问答推荐

我可以从Java模块中排除maven资源文件夹吗?

@ EnableRouting注释在Kotlin项目中不工作

Java Streams在矩阵遍历中的性能影响

SQlite for Android无法使用json_group_array/json_object

JDK22执行repackage of goal org. springframework. boot:spring—boot—maven—plugin:3.2.3:repackage failed:unsupported class file major version 66—>

JVM会优化这个数学运算吗?

现场观看Android Studio中的变化

计算两个浮点数之间的距离是否对称?

返回响应时,CamelCase命名约定不起作用

在Java中将int[]矩阵添加到ArrayList中,但出现错误

错误:不兼容的类型:Double不能转换为Float

Android应用程序为错误的显示类型 Select 尺寸文件

为什么这种递归会有这样的行为?

在不使用instanceof或强制转换的情况下从父类变量调用子类方法

未调用OnBackPressedCallback-Activitiy立即终止

Java System.getProperty在哪里检索user.home?

让标签占用JavaFX中HBox的所有可用空间

org.springframework.web.HttpRequestMethodNotSupportedException:请求方法';帖子';不支持

spring 数据Elastic search 与 spring 启动数据Elastic search 之间的区别是什么?

如何显示新布局