使用 Stream 从超类向下转换为多个子类

Downcasting from superclass to several subclasses using Stream

这是我的第一个 post,这将是一个艰难的过程。

我们有一个 Employee class 元素的列表,它同时可以是 5 种子class 类型的元素:ApprenticeEmployeeSalariedEmployeeCommissionEmployeeCommissionEmployeeWithSalaryHourlyEmployee,它们都包含在同一个列表 employee 中。

ApprenticeEmployee:没有实施 calculateSalary()

SalariedEmployee、CommissionEmployee、CommissionEmployeeWithSalary 和 hourlyEWmployee:实施 calculateSalary()。

这道题需要用Stream计算平均工资。我试过使用过滤器和 mapingToDouble 来做到这一点。问题是沮丧,因为我们不允许使用条件(if-else),因为它说我们正在使用“声明性语言”,而条件违背了它的理念。我如何根据它们的 subclass 向下转换元素?我试过 getClass();但返回的 class 始终是 Employee,而不是 subclass。我试过的代码是:

public Double averageSalary() {
    return  employees.stream()
            .filter(employee -> !(employee instanceof ApprenticeEmployee))
            .mapToDouble(employee -> { 
                (employee.getClass()).cast(employee);
                return employee.calculateSalary();
            })
            .average()
            .getAsDouble();
}

calculateSalary() 是来自接口 Payroll 的方法,由 5 个子 class 中的 4 个实现,除了 ApprenticeEmployee

抱歉,如果我没有以正确的方式输入代码,我是新手!提前致谢!

我建议添加一个接口,其中将分配“calculateSalary”方法。例如,我们将其命名为“CanCalculateSalary”。该接口将由所有需要能够计算工资的Employee 类实现。所以你的代码看起来像这样:

 return employees.stream()
        .filter(CanCalculateSalary.class::isInstance)
        .mapToDouble(employee -> ((CanCalculateSalary)employee).calculateSalary())
        .average()
        .getAsDouble();

有了关于接口声明方法的信息就很简单了。

public Double averageSalary() {
    return  employees.stream()
            .filter(employee -> employee instanceof Payroll)
            .mapToDouble(employee -> ((Payroll) employee).calculateSalary())
            .average()
            .getAsDouble();
}

这还有更多优点:它允许将来添加更多 Employee 子类,其中一些可能实现 Payroll,而另一些可能不会。你仍然不需要修改上面的代码(但用新的子类再次测试)。