在方法覆盖中使用子类型作为参数
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
- 因此子类方法中的参数可能是 Mammal
或 Animal
(两者都将接受类型为 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) {
}
}
}
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
- 因此子类方法中的参数可能是 Mammal
或 Animal
(两者都将接受类型为 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) {
}
}
}