Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning derived class instance from a base class

Tags:

c#

inheritance

The title may be unclear, but please look at the pattern below

public abstract class Animal
{

    public abstract Dog GetDog { get; }

    public abstract Cat GetCat { get; }

}

public class Dog : Animal
{

    public override Dog GetDog {
        get { return this; }
    }

    public override Cat GetCat {
        get { return null; }
    }

}

Is this considered a bad practice to have properties in the base class, return derived types. Or should I do something like

public abstract AnimalTypeEnum AnimalType { get; }

EDIT: Based on the comments, I guess I should be more clear on what I am trying to achieve. A new instance of the Dog or Cat class would be created by a separate function based on certain criteria and would then return Animal type to the caller. The calling method would check the type of the returned instance and use it accordingly.

public Animal CreateAnimal(string path)
{

    //Process the document in path and create either a new instance of dog or cat

    Dog dg = new Dog();

    return dg;

}
like image 316
swiftgp Avatar asked Oct 18 '12 18:10

swiftgp


3 Answers

If you only want the animal you are deriving from you can do this:

public abstract class Animal<T> where T: Animal<T>
{
    public T GetAnimal 
    {
        get { return (T)this; }
    }
}

public class Dog : Animal<Dog>
{
}

public class Cat : Animal<Cat>
{
}

public class Giraffe : Animal<Giraffe>
{
}

You call this way:

var cat = new Cat();
var dog = new Dog();
var giraffe = new Giraffe();
Cat cat2 = cat.GetAnimal;
Dog dog2 = dog.GetAnimal;
Giraffe giraffe2 = giraffe.GetAnimal;
like image 56
Alex Siepman Avatar answered Nov 04 '22 04:11

Alex Siepman


The calling method would check the type of the returned instance and use it accordingly.

There's your problem. It's code smell to need to do that. You should be able to treat whatever it is as just an object, rather than treating dogs and cats differently.

If you need to display the content of either animal, then override the ToString method on both classes and just call ToString on animal. If you need to know the name of the dog or cat then add a Name property to Animal. If at all possible you should be using polymorphism here so that whatever is using the object treads it as just an Animal and simply involves different things happening as a result of different implementations of the same method.

If you really, really do need to know whether the Animal is a Dog or a Cat then you can use the is or as operators; you don't need to add all of the code that you've shown in the OP.

like image 40
Servy Avatar answered Nov 04 '22 03:11

Servy


Nah you are doing it wrong.

The better thing would be to have a single method.

public abstract Animal getAnimal();

Any derived class will then know how to return itself. I hope that makes sense. But then I don't think you would want to return an Animal either. Doesn't make sense.

Animal dog = new Dog() ;
dog.getAnimal(); 

confusing right?

You could have an array of Animals/List, iterate through the collection and check like so:

if(animal is Dog)

But still you are checking the type. If you want to use a base class have it so that it makes sense and exposes a common method.

like image 23
Lews Therin Avatar answered Nov 04 '22 05:11

Lews Therin