Java - 通过构造函数将泛型列表传递给类

Joh*_*des 4 java generics polymorphism inheritance

我一直在尝试使用泛型和多态.我遇到了一个我无法理解的问题.

说我有

public abstract class Animal {
    private age;
    private weight;

    public Animal(){}

    public void Move(){
        //stuff
    }

    public void Eat(){
        //stuff
    }

    //Getters and setters
}
Run Code Online (Sandbox Code Playgroud)

然后

public Cat extends Animal {
    //Constructors
}

public Snake extends Animal {
    //Constructors
    public void ShedSkin(){
        //stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

我也有自己的班级"MyAbstractClass".就在这里,我似乎无法解决问题.

public abstract class MyAbstractClass {
    private List<Animal> myAnimalList;

    public MyAbstractClass(){}

    public MyAbstractClass(List<? extends Animal> animalList) {
        this.myAnimalList = animalList;
    }

    public List<Animal> getAnimalList() {
        return myAnimalList;
    }

    //Stuff which DOES NOT add to the list
}
Run Code Online (Sandbox Code Playgroud)

我希望能够做到:

public class MyCatClass extends MyAbstractClass {
    public MyCatClass(List<Cat> catList) {
        super(catList);
    }
}

public class MySnakeClass extends MyAbstractClass {
    public MySnakeClass(List<Snake> snakeList) {
        super(snakeList);
    }

    public ShedSkin(){
        (Snake)getAnimalList().get(0).ShedSkin(); //Dont worry about indexing
    }
}
Run Code Online (Sandbox Code Playgroud)

然后

public static void main(string[] args) {
    //Make list of cats
    //Make list of snakes

    MyCatClass cats = new MyCatClass(catList);
    MySnakeClass snakes = new MySnakeClass(snakeList);

    snakes.ShedSkin();
}
Run Code Online (Sandbox Code Playgroud)

这对我不起作用.它无法编译public MyAbstractClass(List<? extends Animal> animalList).这有点超过我的java经验,非常感谢一些指导.我希望示例课程足够清楚,以了解我的意图.

编译告诉我:java.util.List<Animal> in MyAbstractClass cannot be applied to java.util.List<capture<? extends Animal>> 谢谢.

编辑:看起来我必须说出我正在尝试做的事情.我有一个动物列表,可能有或没有比超类更多的字段和方法,但它们都扩展了超类.我还想要一个类,它接收单一类型动物的列表,并在List中的每个元素上或上方调用方法.我不会在列表中添加任何内容,因此不应该是一个问题.我这样分裂的原因是因为在所有动物之间,有很多相似之处,但有些动物有特色.列入名单的班级需要能够处理这些特殊性.因此,worker类扩展了一个超类并实现了额外的方法.

编辑2:解决了!

public abstract class MyAbstractClass {
        private List<? extends Animal> myAnimalList;

        public MyAbstractClass(){}

        public MyAbstractClass(List<? extends Animal> animalList) {
            this.myAnimalList = animalList;
        }

        public List<Animal> getAnimalList() {
            return myAnimalList;
        }

        //Stuff which DOES NOT add to the list
    }
Run Code Online (Sandbox Code Playgroud)

字段和构造函数都需要List<? extends Animal> foobar.建设性的头脑风暴会议!

编辑3:迪马的方法更好.

Dim*_*ima 5

好吧,你不能分配List<? extends Animal>给a List<Animal>,因为列表不是协变的:前者不是后者的子类.

您需要将基类成员(以及返回类型getAnimalList())的声明更改为List<? extends Animal>.你在其中一条评论中提到过,这样做会给你带来一些其他的错误MyCatClass,但你必须弄错,如果基类中的所有东西都被正确地声明(不是List<Animal>,但是List<? extends Animal>),那么该类应该没问题.

这一行:(Snake)getAnimalList().get(0).ShedSkin()可能是导致你烦恼的那一行.首先,你需要围绕蛇的一对括号:((Snake) getAnimalList().get(0)).ShedSkin(),第二,再次,你不能强制List<Animal>转换List<Snake>,确保getAnimalList()声明返回List<? extends Animal>,然后一切都应该编译.

我认为,在您的情况下,更好的选择是参数化基类:

public abstract class MyAbstractClass<T extends Animal> {
    private List<T> myAnimalList;
    public MyAbstractClass(List<T> animals) { myAnimalList = animals; }
    public List<T> getAnimalList() { return myAnimalList; }
    //etc.
}

public class MyCatClass extends MyAbstractClass<Cat> {
     public MyCatClass(List<Cat> cats) { super(cats); }
}
public class MySnakeClass extends MyAbstractClass<Snake> {
     public MySnakeClass(List<Snake> snakes) { super(snakes); }
     public ShedSkin() { getAnimalList().get(0).ShedSkin(); }
}
Run Code Online (Sandbox Code Playgroud)

这样你就不需要在任何地方进行投射,因为列表的类型总是完全已知.