HereBeeBees
HereBeeBees

Reputation: 145

Retrieve class type, and instantiate a new one of same type

I have a class Animals, which has two subclasses Cat and Dog. I want to write a reproduction method. Since both Cats and Dogs reproduce, such a method should go in Animals, and obviously cats should only spawn cats, etc. So in the super class Animals I have something like this:

public void Reproduce(){
   addAnimal(new Type);
}

where Type denotes the class that we want to make another of (so either cat or dog). Of course, I want to write the code so that I could add other classes of animals later, like horse or something. So what I want is something like this:

public void Reproduce(){
   addAnimal(new this);
}

so that cat.Reproduce() would launch a new instance of the class Cat, and dog.Reproduce() would instantiate a new Dog, etc.

Is there a way to do this? Or is there a way for the method to retrieve the class type of the instance calling it, and then instantiating a new one?

EDIT: To make it more clear, I have found a few different ways to find out the current class, such as this.getClass();. However, I have not found a way to use that information to create a new class of the same type. Doing something like this:

Class c = this.getClass();
Animals offspring = new c; 

does not work.

Upvotes: 0

Views: 47

Answers (1)

Ivan
Ivan

Reputation: 8758

There are two options. First is to make your classes implementing Cloneable interface like this

class Cat implements Cloneable {
  // all your properties and methods

  @Override
  public Cat clone() throws CloneNotSupportedException {
        return (Cat)super.clone(); // if you need deep copy you might write your custom code here
  }

  public void Reproduce(){
    Cat c = this.clone();
    // change some properties of object c if needed
    addAnimal(c);
  }
}

Second option is to use reflection (you might need to add try{} catch() block around usage of reflection)

public void Reproduce() {
   Constructor c = tc.getClass().getDeclaredConstructor(String.calss, Integer.class); //pass types of parameters as in consrtuctor you want to use. In 
            //this case I assume that Cat class has constructor with first parameter of type String and second parameter of type Integer
   Cat cat = (Cat)c.newInstance("someString", 2); 
   // change some properties of object c if needed
   addAnimal(cat);
}

Upvotes: 1

Related Questions