我有这个代码:
public abstract class animal {
public final static int elephent = 1;
public final static int dog = 2;
和两个子类:
public class elephant extends animal {
public final static int type = animal.elephent;
public elephant (String name){
super(name);
}
}
public class dog extends animal {
public final static int type = animal.dog;
public dog (String name){
super(name);
}
}
现在,假设我有一个字符列表,其中包含字母 E-elephant 和 D-dog。 和相同大小的动物类的空列表。 对于第一个列表中的每个字符,我想创建一个正确动物的新实例。 示例:[“d”,“e”,“d”] 会给我一个列表:[新狗,新大象,新狗] 希望我说清楚了, 预先感谢您的帮助。
最佳答案
这个设计并不是最优的。您用整数变量指示类型,这确实不是一个好主意。
第一个改进:将类型指示设为枚举。
public enum AnimalType {
ELEPHANT, DOG
}
现在在您的动物类中添加一个类型字段:
public abstract class Animal {
private final AnimalType type;
private final String name;
protected Animal(AnimalType type, String name) {
this.type = Objects.requireNonNull(type);
this.name = Objects.requireNonNull(name);
}
// more fields and methods here
}
大象看起来像这样(狗也类似):
public class Elephant extends Animal {
public Elephant(String name) {
super(AnimalType.ELEPHANT, name);
}
// more fields and methods here
}
主要缺点:每次添加新的动物类型时,都必须添加新类并向枚举添加类型。这不是最好的设计。此外,类型枚举并不是真正需要的,因为子类型已经保存了类型信息
Elephant 类的实例是大象(狗也是如此)。它不需要类型字段。
第二个改进:完全删除类型指示。没有整数,没有枚举。只要有抽象类和子类即可。
现在你的问题是,如何从任何字符输入中获取正确的实例。这称为映射。您想要 map
the character 'E' to the class
Elephant
.the character 'D' to the class
Dog
.
这可以通过 Java Map
来实现:
Map<Character, Class<? extends Animal>> charToAnimal = new HashMap<>();
charToAnimal.put('E', Elephant.class);
charToAnimal.put('D', Dog.class);
Class<? extends Animal> animalClass = charToAnimal.get('E');
String name = ...;
Animal animal = animalClass.getConstructor(String.class).newInstance(name); // will be an Elephant instance
应该在您需要该行为的任何类中维护此映射,或者如果您刚刚学习如何做到这一点,则可以在 main 方法中维护此映射。
请注意,我使用了一种称为反射的 Java 机制,只是为了创建一个实例,因为没有其他通用方法来处理实例化。
另一种方法是执行相同操作的方法:
public Animal createAnimal(char c, String name) {
if (c == 'E') {
return new Elephant(name);
} else if (c == 'D') {
return new Dog(name);
} else {
throw new IllegalArgumentException(c);
}
}
无论哪种方式,您不仅必须添加一个新的动物子类,而且还必须向映射添加一个条目(见上文)或向该方法添加一个 if 分支。
<小时/>编辑,当我再次思考这个场景时。
您可以采用枚举方法并将类实例化放入此枚举中。采用上述动物类别和以下类型枚举(未选中):
public enum AnimalType {
ELEPHANT('E', Elephant.class),
DOG('D', Dog.class);
private static final Map<Character, Class<? extends Animal>> CHAR_TO_ANIMAL = new HashMap<>();
AnimalType(char c, Class<? extends Animal> animalClass) {
CHAR_TO_ANIMAL.put(c, animalClass)
}
public Animal createAnimal(char c, String name) {
if (c == 'E') {
return new Elephant(name);
} else if (c == 'D') {
return new Dog(name);
} else {
throw new IllegalArgumentException(c);
}
}
}
关于java-从列表中调用子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22728702/