Java 默认方法的协变返回类型

Java 默认方法的协变返回类型,java,default-method,covariant-return-types,Java,Default Method,Covariant Return Types,我可以用协变返回类型重写方法,但是否可以用协变返回类型重写默认值方法?在下面的示例中,我希望在不重写默认方法的情况下重写getFirstLeg,但Java不允许这样做。我也不想让Animal成为一个通用接口,因为可能有很多参数,Animal在很多地方都被使用 interface Leg { } interface Animal { List<? extends Leg> getLegs(); default Leg getFirstLeg() {

我可以用协变返回类型重写方法,但是否可以用协变返回类型重写默认值方法?在下面的示例中,我希望在不重写默认方法的情况下重写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
}
接口腿{
}
界面动物{

List是的,Java确实有继承方法的协变返回类型。但这里的问题不是
getFirstLeg
是一个
默认的
方法,而是Java的泛型不是协变的;它们是不变的。也就是说,
List
不是一个
列表如果你想要协变,请键入
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
}
接口腿{
}
界面动物{
列出getLegs();
默认的getFirstLeg(){
返回getLegs().get(0);
}
}
抽象类AnimalImpl实现了Animal{
私人名单;
@凌驾
公共列表getLegs(){
返回支腿;
}
}
接口鸭腿延伸腿{
}
鸭与动物的接口{
}
类DuckImpl扩展AnimalImpl实现Duck{
//没有错误
}

请看我文章的最后一句话。我担心让动物(或任何其他广泛使用的界面)成为通用的,因为如果我们想更改参数,我们必须更改很多地方。请看我文章的最后一句话。我担心让动物(或任何其他广泛使用的界面)成为通用的泛型,因为如果我们想更改一个参数,我们将不得不更改很多位置。虽然列表不是一个列表制作
Animal
generic,但我看到的唯一解决问题的方法正是因为Java泛型是不变的。此外,
列表如果是这样,为什么我可以使用列表
interface Animal<T extends Leg> {
    List<T> getLegs();

    default T getFirstLeg() {
        return getLegs().get(0);
    }
}
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
}
class DuckImpl extends AnimalImpl<DuckLeg> implements Animal<DuckLeg> {

}
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
}