Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating Objects According to an Input File

Tags:

java

I have a task that needs to be done but I am really stuck.

Basically, I've some inheritance relations like this:

Animal

Pet WildAnimal

Bird Cat Dog Fish ||Snake Eagle

Animal is the parent of Pet and Wild Animal. Pet is the parent of Bird, Cat, Dog, Fish. WildAnimal is the parent of Snake and Eagle.

The task wants me to read inputs from a file which is "input.txt" and create Animal objects.

"input.txt" is like:

kiwi Bird charlie Eagle mango Fish pepper Dog angle Cat tweety Bird bob Dog ziggy Snake

I can get all of the names but I couldn't figure out how to understand which kind of object every single name represent.

Here is the main method:

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();
    }
}

Here is the animal class:

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());
}

}

I can add all the other classes if you want but i don't think you're gonna need them.

like image 300
M.Soyturk Avatar asked Jan 09 '17 09:01

M.Soyturk


People also ask

What is object creation?

The Object. create() method creates a new object, using an existing object as the prototype of the newly created object.

What is the syntax for creating and object?

The syntax for creating an object is: ClassName object = new ClassName();


2 Answers

You have to instantiate objects of your specific class; based on the incoming string.

Example: if the class name from the file is Bird ... then you have to call new Bird() somehow.

There are two ways to get there:

  1. Using reflection (you can actually instantiate classes "by string"; without knowing anything about that class)
  2. By using a switch statement

Reflection is more of an "advanced" topic (and very easy to use the wrong); so I really do recommend you to go for option 2, like:

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);
  }
}

(the above code is meant as "fyi" - I didn't run it through the compiler; it is meant to give you one idea how this could be done).

Some notes beyond that:

  • Consider using a final field for those properties of your objects that can't change. You don't need a setter for the name then; just give the name as parameter to the constructor. In other words: only make those fields "changeable" that make sense to be changed. Anything else should better be final.
  • Instead of using an array with 100 empty slots, you could use a java.util.ArrayList and just add as many new animals as you find in that file.
  • Consider adding equals/hashCode methods to your Animal class (not mandatory, but you should read why that makes sense very often).
  • Probably most importantly: consider not putting all those different methods directly into your base class. It might make more sense to create either abstract subclasses that add certain functions, or use interface, like interface FlyingAnymal { void fly() }; which your specific subclasses would then implement. It is not really good practice to put a lot of methods on your base class ... that simply dont make sense for all of the sub classes.
like image 170
GhostCat Avatar answered Oct 16 '22 20:10

GhostCat


If you really want to use reflection to do so (which I would also discourage), here's sample code :

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);

I don't think the code is so complex, but few people have ever used reflection so they'll have problems maintaining it, and it is tightly coupled with your classes definitions so it will probably have to be maintained a lot.

like image 25
Aaron Avatar answered Oct 16 '22 20:10

Aaron