使用多态性初始化对象列表
Initializing list of objects using polymorphism
我有一个关于应用多态性的问题:假设我有一个 class Bird
,并且我有很多 class 扩展它(比如 Pigeon
, Falcon
等等)。
接下来,我有一个Cage
class。在这个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
.
类型的引用
我有一个关于应用多态性的问题:假设我有一个 class Bird
,并且我有很多 class 扩展它(比如 Pigeon
, Falcon
等等)。
接下来,我有一个Cage
class。在这个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
.