我可以使用协变返回类型覆盖一个方法,但是是否可以使用协变返回类型覆盖默认方法?在下面的示例中,我想覆盖getFirstLeg而不重写默认方法,但Java不允许这样做。我也不想让Animal成为通用接口,因为可能有很多参数,很多地方都使用Animal。
interface Leg {
}
interface Animal {
List<? extends Leg> getLegs();
default Leg getFirstLeg() {
return getLegs().get(0);
}
}
abstract class AnimalImpl<T extends Leg> implements Animal {
private List<T> legs;
@Override
public List<T> getLegs() {
return legs;
}
}
interface DuckLeg extends Leg {
}
interface Duck extends Animal {
@Override
List<? extends DuckLeg> getLegs(); //covariant return type
@Override
DuckLeg getFirstLeg(); //I do not want to rewrite this method
}
class DuckImpl extends AnimalImpl<DuckLeg> implements Duck {
//Error: java: DuckImpl is not abstract and does not override abstract method getFirstLeg() in Duck
}
更新:以下代码编译,但新问题是Duck不再是Animal。
interface Leg {
}
interface AnimalGeneric<T extends Leg> {
List<? extends T> getLegs();
default T getFirstLeg() {
return getLegs().get(0);
}
}
abstract class AnimalImpl<T extends Leg> implements AnimalGeneric<T> {
private List<T> legs;
@Override
public List<T> getLegs() {
return legs;
}
}
interface Animal extends AnimalGeneric<Leg> {
//empty
}
interface BirdLeg extends Leg {
}
interface BirdGeneric<T extends BirdLeg> extends AnimalGeneric<T> {
}
class BirdImpl<T extends BirdLeg> extends AnimalImpl<T> implements BirdGeneric<T> {
}
interface Bird extends BirdGeneric<BirdLeg> {
//empty
}
interface DuckLeg extends BirdLeg {
}
class DuckImpl extends BirdImpl<DuckLeg> implements Duck {
}
interface Duck extends BirdGeneric<DuckLeg> {
}
答案 0 :(得分:0)
是的,Java确实有继承方法的协变返回类型。但问题不在于getFirstLeg
是一种default
方法,而是Java的泛型不是协变的;他们不变。即List<DuckLeg>
不是List<? extends Leg>
,即使DuckLeg
是Leg
。
但是你可以通过使Animal
接口通用来解决这个问题,以便type参数可以根据子接口进行更改。
interface Animal<T extends Leg> {
List<T> getLegs();
default T getFirstLeg() {
return getLegs().get(0);
}
}
然后Duck
也有一个类型参数,但不再需要覆盖任何东西。类型参数DuckLeg
已分配给T
。
interface Duck extends Animal<DuckLeg> {
// able to remove the override of getLegs
//@Override
//List<DuckLeg> getLegs(); //covariant return type
// able to remove the override of getFirstLeg
//@Override
//DuckLeg getFirstLeg(); //I do not want to rewrite this method
}
然后你的DuckImpl
课将继承正确的一切,你不会得到&#34;不抽象,不会覆盖抽象方法&#34;错误。
当然,对于Duck
的空声明,您可能根本不需要它。只需DuckImpl
实施Animal<DuckLeg>
。
class DuckImpl extends AnimalImpl<DuckLeg> implements Animal<DuckLeg> {
}
答案 1 :(得分:0)
如果您想要协方差,请输入Leg
。然后,您可以删除大部分代码。
编译:
interface Leg {
}
interface Animal<T extends Leg> {
List<T> getLegs();
default T getFirstLeg() {
return getLegs().get(0);
}
}
abstract class AnimalImpl<T extends Leg> implements Animal<T> {
private List<T> legs;
@Override
public List<T> getLegs() {
return legs;
}
}
interface DuckLeg extends Leg {
}
interface Duck extends Animal<DuckLeg> {
}
class DuckImpl extends AnimalImpl<DuckLeg> implements Duck {
// no errors
}