覆盖接口默认方法

时间:2019-01-31 18:53:56

标签: java oop inheritance

使以下代码无法正常工作:

接口:

public interface UOWProcessor {
  public default Integer countUOW(Object args) {
    return 1;
  }
}

实施:

public class ListUOWProcessor implements UOWProcessor {
private Integer total;

@Autowired
private UOWProcessor uowProcessor;

@Override
public Integer countUOW(List<?> args) {
    for (Object arg : args) {
        total += uowProcessor.countUOW(arg);
    }

    return total;
  }
}

编辑:添加第二种实现以明确意图

public class MapUOWProcessor implements UOWProcessor {
    private Integer total;

    @Autowired
    private UOWProcessor uowProcessor;

    @Override
    public Integer countUOW(Map<?, ?> args) {
        for (Object item : args.values()) {
            total += uowProcessor.countUOW(item);
        }

        return total;
    }
}

问题在于@Override注释给出了一个错误the method does not override a method from its superclass。这是Java11。正确的语法是什么?

如果从上方不清楚,这就是我要用英语做的事情:

另一个类将调用接口方法countUOW(未知类型的对象)。

如果存在针对对象类型的此接口的实现(例如,ListUOWProcessor for Lists,MapProcessor for Maps),则将调用该实现,并将迭代并返回总计(基本上是对象数)。递归调用此方法以解决嵌套数组/列表。

如果没有实现,我们可以假定要传递的对象是一些非特定对象,其计数为1。

对于该方法的原始调用,我们应该返回传递的父对象中所有对象的计数,包括嵌套数组或映射中的对象。

我也可以从接口中删除“ default”一词,然后创建一个做同样事情的ObjectUOWProcessor-但是我担心它可能会优先于其他所有实现,因为List,Array,Map都是Object的扩展。

编辑:我知道这不是覆盖,而是覆盖。没有@Override批注的代码是否可以实现所描述的功能?

2 个答案:

答案 0 :(得分:2)

添加@Override注释非常好。因此,编译器通知您您没有正确覆盖countUOW方法。参数类型不同-接口方法采用Object,实现类方法采用List<?>。这意味着您已经重载了该方法,而不是覆盖了它。

您可以执行以下任一操作:

  1. 更改接口方法的签名以使其匹配。

    public default Integer countUOW(List<?> args) {
        return 1;
    }
    
  2. 更改实现类方法的签名以匹配。

    @Override
    public Integer countUOW(Object args) {
        for (Object arg : (List<?>) args) {
            total += uowProcessor.countUOW(arg);
        }
    
        return total;
    }
    
  3. 使接口具有通用性,并让实现类提供类型作为参数。

    public interface UOWProcessor<T> {
        public default Integer countUOW(T args) {
            return 1;
        }
    }
    
    public class ListUOWProcessor implements UOWProcessor<List<?>> {
        // ...
        @Override
        public Integer countUOW(List<?> args) {
            for (Object arg : args) {
                total += uowProcessor.countUOW(arg);
            }
    
            return total;
        }
    }
    

请注意,这与您的方法为default无关。无论是默认方法还是抽象方法,以及覆盖的方法是在接口,抽象类还是具体类中,您都会遇到相同的错误,具有相同的选项来解决问题。

答案 1 :(得分:1)

好吧,您不能在实现中传递String作为参数,因为它期望一个List<?>,而接口清楚地表明,由于所有类都应该可以作为参数传递类扩展了Object。因此,您没有遵循界面中指定的条件。您已经更改了方法的签名,因此不会覆盖它;您正在超载。