這種設計不是最優的。你用一個整型變量表示類型,這真的不是一個好主意。
第一次改進:使類型指示爲枚舉。
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
的一個實例是一頭大象(狗一樣)。它不需要類型字段。
二,改進:完全刪除類型指示。沒有整數,沒有枚舉。只需要抽象類和子類。
現在你的問題,如何從任何字符輸入得到正確的實例。這被稱爲映射。你想要映射
字符'E'到類Elephant
。
字符'D'到類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方法,如果你剛開始學習如何做到這一點。
請注意,我使用了一種名爲reflection的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);
}
}
無論哪種方式,你必須添加不僅NE動物子類,但你必須一個條目添加到地圖上(見上)或方法的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);
}
}
}
這個家庭工作你的嘗試是什麼? – vels4j