我有一个类和一个像这样的接口(interface):
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 的父类(super class)的步骤。因此,对于 DeveloperOnboardingProcess,构造函数可以采用 OnboardingStep<Developer>
的列表元素。或者一个 OnboardStep,其泛型类型是 Developer 的任何父类(super class),包括 Employee 本身。
但是,您不能做的一件事就是传递 List<DeveloperOnboardingStep>
。 List<DeveloperOnboardingStep>
不等于List<OnboardingStep<Developer>>
或List<OnboardingStep<Employee>>
,因为后者有 add
(以及 addAll 等)方法,该方法允许 OnboardingStep、DeveloperOnboardingStep 或 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;
}
关于接受类及其接口(interface)的 Java 类型(逆变),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77375515/