Reputation: 439
I have an Animal
class, and two derived classes: Lion
and Ant
.
I have a method that takes in an Animal
type and I want to return a new instance of the derived type of the animal passed to the function (i.e. a new instance of Lion
).
public Animal Reproduce(Animal p_animal)
{
Type animalType = p_animal.GetType();
if (SameSpecies(p_animal))
return new animalType(RandomName());
}
Upvotes: 1
Views: 109
Reputation: 1131
Since you don't know the type at compile time, you will have to use Reflection. What you are trying to achieve can be done with:
return (Animal)Activator.CreateInstance(animalType, RandomName());
That line is executed at runtime, meaning that, if the type "animalType" is actually not an extension of the class "Animal", this line will fail at runtime. Also, one of the constructors of your type "animalType" needs to receive exactly one argument of whatever type "RandomName()" function returns, otherwise you will also have a runtime error.
EDIT: Reflection has a performance cost and should be avoided when possible. KMoussa suggested a good approach you can follow that avoids reflection and thus is much better than the reflection approach.
Upvotes: 3
Reputation: 1578
There are several ways to achieve this, but what I would suggest is that you create an abstract Reproduce method on your Animal
class and implement it in the derived types. For instance:
public abstract class Animal
{
/* .. other stuff .. */
public abstract Animal Reproduce();
public string RandomName() { /* ... */ }
}
public class Lion : Animal
{
/*... other stuff .. */
public override Animal Reproduce() => new Lion(RandomName());
}
That way you can add any future logic in the Reproduce
method specific to a certain Animal
Upvotes: 4
Reputation: 3017
You could use reflection OR you could keep some type safety and use something called the 'Curiously recurring template pattern'. It uses generics, if you aren't familiar with that concept, I would do some reading up as they are very powerful, useful and prevalent in the .Net Eco system. Any way, here is what I would do
public abstract class Animal<T>
where T : Animal<T>
{
public string Name {get; private set;}
public Animal(string name)
{
Name = name;
}
public abstract T Reproduce();
public static T Reproduce(T animalToReproduce)
{
return animalToReproduce.Reproduce();
}
}
public class Lion : Animal<Lion>
{
public Lion(string name)
: base (name)
{
}
public override Lion Reproduce()
{
return new Lion(RandomName());
}
}
Then you can just call Animal.Reproduce(yourAnimalInstance)
this will return an object of the correct type. For example
Lion myLion = GetALionFromSomewhere();
Lion babyLion = Animal.Reproduce(myLion);
That will compile and you've got all the goodness of type safety
Upvotes: 0