为什么定义协变 compareTo 方法被认为是不好的做法?

2022-09-02 04:02:30

下面是我代码中的一个示例:

基类:

abstract class AbstractBase implements Comparable<AbstractBase> {
    private int a;
    private int b;

    public int compareTo(AbstractBase other) {
        // compare using a and b
    }
}

实现:

class Impl extends AbstractBase {
private int c;

public int compareTo(Impl other) {
    // compare using a, b and c with c having higher impact than b in AbstractBase
}

FindBugs 将此报告为问题。但这是为什么呢?可能会发生什么?

如何正确实施解决方案?


答案 1

Impl#compareTo(Impl)不覆盖,因为它们没有相同的签名。换句话说,例如,在使用时不会调用它。AbstractBase#compareTo(AbstractBase)Collections#sort


答案 2

编辑:添加了无铸造的解决方案

如果您不想投射,可以尝试以下操作。

将基类更改为:

abstract class AbstractBase<T extends AbstractBase<?>> implements Comparable<T> {
//...
    public int compareTo(T other) {
      //... 
    }
}

你 Impl 类是:

class Impl extends AbstractBase<Impl> {
//...
    @Override
    public int compareTo(Impl other) {
    //...
    }
}

铸造解决方案:

一个可能的解决方案是重写 Impl 类中的 compareTo(AbstractBase) 方法,并显式检查是否传入了 Impl 的实例:

   class Impl extends AbstractBase {
   //...
        @Override
        public int compareTo(AbstractBase other) {

            if (other instanceof Impl) {

                int compC = Integer.compare(c, ((Impl) other).c);

                if (compC == 0) {
                    return super.compareTo(other);
                }
                return compC;
            }

            return super.compareTo(other);
        }
    }

推荐