使用多态性初始化对象列表

Initializing list of objects using polymorphism

我有一个关于应用多态性的问题:假设我有一个 class Bird,并且我有很多 class 扩展它(比如 PigeonFalcon 等等)。 接下来,我有一个Cageclass。在这个class中,我想列出一个笼子里的鸟(每个笼子里只能住一种鸟)。

因此,我不知道列表的扩展类型(A Pigeon?或者可能是 Eagle?),我唯一知道的是它将是 Bird.

如果Pigeon extends Bird

使用多态性,我可以将一只鸟声明为: Bird tom = new Pigeon(); 而不是 Pigeon tom = new Pigeon();

那么为什么我不能在构造函数中初始化类似的东西: [...]

private List<Bird> birdList;

    public Cage() {
        this.birdList = new ArrayList<Pigeon>();
        /* Instead of birdList = new ArrayList<Bird>(); */
    }

如果你做不到,是否可以通过其他方式实现我的目标?

您可以添加到您的 bird arraylist pidgeon,然后测试 :

的实例
private List<Bird> birdList;

public Cage(){
    this.birdList = new ArrayList<>();
    birdList.add(new Pidgeon());

    //...
    //Checking if it is a Pidgeon :
    if(birdList.get(i) instanceof Pidgeon) {

        //It is a pidgeon

    }
}

由于每个笼子里只住一种鸟,您可以使用通用类型来键入您的笼子class。

例如,Cage<T> 将这样定义鸟的列表:List<T> birdList.

你不能这样做:

列出鸟类 = new ArrayList();

在 java 中。左边的通用类型必须完全相等(或者可能不必相等,如果游戏中有通配符 - ? extends T 或 ? super T)到右边的通用类型。

如果可能的话,就不可能将新的 Eagle 添加到声明为 Bird 列表的列表中 - 这没有任何意义

您可以做的是:

List<Bird> birds = new ArrayList<Bird>();
birds.add(new Pigeon());

Bird 的所有家族,包括 Pigeon 的)

或:

List<? extends Bird> birds = new ArrayList<Pigeon>();
birds.add(new Pigeon()); // Adding is immpossible now - list can be read only now! 

您可能想要的是为您的 Cage 使用通用类型来捕获笼中生活的确切种类的鸟。像这样:

import java.util.ArrayList;
import java.util.List;

public class Cage<T extends Bird> {

    private List<T> birdList;

    public Cage() {
        birdList = new ArrayList<T>();
    }

    public void addBird(T bird) {
        birdList.add(bird);
    }

}

然后你会像这样使用笼子:

Cage<Eagle> eagleCage = new Cage<Eagle>();
eagleCage.addBird(new Eagle());

你不能做 List<Bird> birdList = new ArrayList<Pidgeon>() 的原因是有人可以使用 birdList 引用将任何 Bird 子类写入你的 ArrayList<Pidgin>。类型检查器不允许这样做,Pidgin 的列表必须仅包含 Pidgin 个实例。

Arne 在 Cage 上使用类型参数给出了一个解决方案。如果这不是你想要做的,你可以用 wildcard type.

声明 birdList

您的示例如下所示:

class Bird {}
class Pidgeon extends Bird {}

class Cage {
    // This is a wildcard type and can contain lists of any
    // subtype to Bird, but you can't add elements to it.
    private List<? extends Bird> birdList;

    public Cage() {
        this.birdList = new ArrayList<Pidgeon>();
    }
}

像这样的 上限通配符类型 告诉编译器 birdList 包含 一些未知 子类的列表 Bird。这会导致您无法向列表中添加任何元素,因为您无法确定添加了正确的子类型,并且当您从列表中读取时,您将获得 Bird.

类型的引用