在方法覆盖中使用子类型作为参数

Using subtype for parameter in method override

public abstract class SequenceItemHolder {

    public SequenceItemHolder(View itemView) {
    }

    public abstract void setData(SequenceRowElement.RowElement rowElement);


        public static class TesteItemHolder extends SequenceItemHolder {

        public TesteItemHolder(View itemView) {
        }

        @Override
        public void setData(SequenceRowElement.TestRowElement rowElement) {
        }
   }
}

有人能解释一下为什么我在重写中遇到编译错误吗?

请问如何解决(不使用界面)?


注意:TestRowElement 扩展了 RowElement

错误 1

public SequenceItemHolder(View itemView) {
    super(itemView);
    }

对象没有将视图作为参数的构造函数。删除超级调用。

错误 2

public abstract void setData(SequenceRowElement.RowElement rowElement) {}

抽象方法不应该有主体。将其替换为:

public abstract void setData(SequenceRowElement.RowElement rowElement);

错误 3

您的重写方法应具有与抽象方法相同的参数类型。

您没有覆盖方法(= 相同的方法签名),您正在重载它(= 相同的方法名称,不同的参数)

public abstract void setData(SequenceRowElement.RowElement rowElement) {}

@Override
public void setData(SequenceRowElement.TestRowElement rowElement) {
}

您的第一个函数(在 SequenceItemHolder 中)采用 SequenceRowElement.RowElement 作为参数,您的第二个函数采用 SequenceRowElement.TestRowElement 作为参数。 因此,@Override是错误的。

这就是所谓的正式名称 covariance and contravariance

简单地说,如果你的类型层次结构为Animal > Mammal > Dog,并且基方法

Mammal foo(Mammal arg)

这些被允许作为覆盖:

  • Mammal foo(Mammal arg)
    
  • Mammal foo(Animal arg)
    
  • Dog    foo(Mammal arg)
    
  • Dog    foo(Animal arg)
    

也就是说,您可以扩大参数类型(允许在子类的方法中输入更通用的内容)并缩小 returned 值(声明您将 return 更具体的类型).

原因是,调用者必须能够使用原始签名调用覆盖的方法 - 因此子类方法不能具有更具体的参数或更通用的 return 值。在上面的示例中,调用者必须能够使用 Mammal 类型的参数调用 foo 并且 return 值必须是 Mammal - 因此子类方法中的参数可能是 MammalAnimal(两者都将接受类型为 Mammal 的实际参数),并且可能 return 一个 Mammal 或一个 Dog(两者都是可以存储在 Mammal).

类型的变量中

像这样:

    public abstract class SequenceItemHolder {

    public SequenceItemHolder(View itemView) {
    }

    public abstract void setData(SequenceRowElement.RowElement rowElement);

    public static class TesteItemHolder extends SequenceItemHolder {

        public TesteItemHolder(View itemView) {
            super(itemView);
        }

        @Override
        public void setData(SequenceRowElement.RowElement rowElement) {          
        }
    }
}