根据输入文件创建对象

时间:2017-01-09 09:15:49

标签: java

我有一项需要完成的任务,但我真的被卡住了。

基本上,我有一些像这样的继承关系:

动物

Pet WildAnimal

鸟猫狗鱼||蛇鹰

动物是宠物和野生动物的父母。 宠物是鸟,猫,狗,鱼的父母。 WildAnimal是Snake and Eagle的父母。

该任务要求我从“input.txt”文件中读取输入并创建Animal对象。

“input.txt”就像:

奇异鸟 查理鹰 芒果鱼 胡椒狗 角度猫 tweety Bird 鲍勃狗 ziggy Snake

我可以获得所有的名字,但我无法弄清楚如何理解每个名称代表哪种对象。

这是主要方法:

public static void main(String[] args) throws IOException {
    String s ="";
    int nameCounter = 0;
    Animal[] animals = new Animal[100]; 

    try{
    Scanner input = new Scanner(Paths.get("input.txt"));

        while (input.hasNext()) {
            s = input.next();
            Animal animal = new Animal(s);
            animals[nameCounter] = animal;
            nameCounter += 2;
        }
    }catch(Exception e){
        e.printStackTrace();
    }
}

这是动物类:

public class Animal {
private String name;
private int numberOfLegs;
private int numberOfWings;  

public Animal(String name){
    this.name = name;
    numberOfLegs = 4;
    numberOfWings = 0;
}

public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public int getNumberOfLegs() {
    return numberOfLegs;
}
public void setNumberOfLegs(int numberOfLegs) {
    this.numberOfLegs = numberOfLegs;
}
public int getNumberOfWings() {
    return numberOfWings;
}
public void setNumberOfWings(int numberOfWings) {
    this.numberOfWings = numberOfWings;
}
public void talk(){
    System.out.printf("<Silence>");
}
public void fly(){
    System.out.printf("%s cannot fly", getName());
}
public void run(){
    System.out.printf("%s is running", getName());
}

}

如果你愿意,我可以添加所有其他课程,但我不认为你会需要它们。

2 个答案:

答案 0 :(得分:4)

您必须实例化特定类的对象;基于传入的字符串。

示例:如果文件中的类名是Bird ...那么你必须以某种方式调用new Bird()

有两种方法可以实现目标:

  1. 使用反射(你实际上可以实例化类&#34;字符串&#34 ;;不知道关于该类的任何
  2. 使用switch语句
  3. Reflection 更像是&#34;高级&#34;主题(并且很容易使用错误);所以我真的建议你去选项2,比如:

    private Animal createAnimalFor(String className, String animalName) {
      switch (className) {
        case "Bird": return new Bird(animalName); 
        ...
        default: throw new IllegalArgumentException("Dont know how to create object for unknown class: " + className);
      }
    }
    

    (以上代码的意思是&#34; fyi&#34; - 我没有通过编译器运行它;它是为了给你一个的想法如何完成)。

    除此之外的一些注释:

    • 考虑将 final 字段用于无法更改的对象属性。您不需要 setter 作为名称;只需将名称作为参数提供给构造函数。换句话说:只做那些领域&#34;多变的&#34;有意义的改变。其他任何事情最好 final
    • 您可以使用java.util.ArrayList而不是使用包含100个空插槽的数组,只需添加您在该文件中找到的新动物。
    • 考虑将equals / hashCode方法添加到Animal类中(不是必需的,但是您应该经常阅读为什么有意义)。
    • 可能最重要的是:考虑将所有这些不同的方法直接放入您的基类。创建添加某些函数的抽象子类或使用接口(例如您的特定子类将实现的interface FlyingAnymal { void fly() };)可能更有意义。在你的基类上放置很多方法并不是一个好习惯...对于所有子类都没有意义。

答案 1 :(得分:3)

如果您真的想使用反射(我也不鼓励),请参阅以下示例代码:

String name = input.next();
String className = input.next();
// apply transformations to className as needed
Class<Animal> c = (Class<Animal>) Class.forName(className);
Constructor<Animal> constr = c.getDeclaredConstructor(String.class); // retrieves the Animal(String name) constructor
Animal a = constr.newInstance(name);

我不认为代码是如此复杂,但很少有人曾经使用过反射,因此他们在维护它时会遇到问题,并且它与你的类定​​义紧密结合,所以它可能必须是保持了很多。