我正在尝试创建一个可以被一个抽象类的所有子类使用的ArrayList,但是对象类型应该是sublcasses。
为简单起见,以下是一个例子:
有一个名为' Animal'的抽象类,有三个子类叫做' Dog',' Cat'' Pig' 。
所以,我想创建一个&#39; ArrayList<Animal> all
&#39;,子类应该使用此列表将对象存储在其列表中。
因此,必须有&#39; ArrayList<Dog>
&#39;,&#39; ArrayList<Cat>
&#39;和&#39; ArrayList<Pig>
&#39;等等。
我不想循环通过动物&#39;动物&#39; class,然后转换每个对象导致非继承的方法和值无法访问......
我想这样做,这样我就可以更快地遍历对象。
答案 0 :(得分:4)
要为每个子类型提供其类型列表,请将Animal设为通用。
在Animal.java中:
public class Animal<AnimalType extends Animal> {
public List<AnimalType> getAll() {
return all;
}
private List<AnimalType> all = new ArrayList<>();
}
在Dog.java中:
public class Dog extends Animal<Dog> {
public void doSomething() {
for (Dog dog: getAll()) {
}
}
}
通过使动物“通用”,您通常会想要参考您正在处理的特定动物类型。因此,如果您将变量声明为Animal类型,则需要包含类型信息(否则,您将收到有关原始类型的警告)。例如:
Animal<Dog> myFirstDog = ...;
如果你想引用一般的动物,那么你可能会这样做:
Animal<?> myFirstPet = ...;
如果你让你的动物等级更有趣也更通用,那么你可能会说:
Animal<? extends Canine> ...
可能与动物,动物或动物相匹配。
在最后一个例子中:
在Canine.java中:
public class Canine extends Animal<Canine> {
}
在Dog.java中:
public class Dog extends Canine<Dog> {
}
在Coyote.java中:
public class Coyote extends Canine<Coyote> {
}
答案 1 :(得分:0)
你应该使用泛型。例如:
class Animal<T> {
List<T> all
}
class Cat extends Animal<Cat> {...}
我不确定您在扩展和超级关键字中的需求。在我的样本中,猫的列表只能包含猫,而不包含其他动物或猫的子类。
答案 2 :(得分:0)
我根据你的评论改写答案。你说
我想我没有解释清楚。我不需要为每个子类实例使用ArrayList,我需要为每个子类使用一个ArrayList(这意味着它将受到静态保护)。但是,我无法在超类中初始化它,因为我必须键入'ArrayList',而我需要ArrayList和ArrayList
您需要一个全局列表,您可以存储所有动物。再一次,我没有看到你在类层次结构中列出一个点,更不用说受保护的静态列表了。这意味着所有子类共享相同的列表 - 这意味着不可能像你想要的那样实现它。
为什么不将列表提取到存储库中然后将动物存储在那里?您可以随时将它们过滤到您需要的新动物列表中:
public class CrazyAnimalRepositry {
private List<CrazyAnimal> animals = new ArrayList<>();
public <T extends CrazyAnimal> List<T> filterForAnimalType(Class<T> filteringClass){
return animals.stream()
.filter(t -> t.getClass().equals(filteringClass))
.map(t -> (T) t)
.collect(Collectors.toList());
}
public void addAnimal(CrazyAnimal animal){
animals.add(animal);
}
}
您可以按如下方式使用此存储库:
public void testAnimals(){
CrazyAnimalRepositry repositry = new CrazyAnimalRepositry();
Dog dog = new Dog();
Cat myCatz = new Cat();
repositry.addAnimal(dog);
repositry.addAnimal(myCatz);
for(Cat cat : repositry.filterForAnimalType(Cat.class)){
cat.meow();
}
}
您还可以将存储库放在基类Crazy Animal中,并可以从那里访问同一个对象。从那里你可以通过调用 filterForanimalType 并传入你所在的课来过滤列表。