Passing an inherited class

I am trying to use simple code to understand generics in C #. The purpose of this code is to have a trainer who has his own animal and asks him to do various things (for example, jump).

The problem lies in the constructor of the trainer. I would like to be able to pass a dog or a cat. They both inherit from the same class, but since I specified the type definition, it seems that I cannot pass them as an argument, they cannot be valid. Is there a way to specify a general class like "Animal" so that I can transfer a dog or cat and keep it as a member?

class AnimalDefinition
{
    public Fur Fur;
}

class DogDefinition : AnimalDefinition
{
    public BarkSound Bark;
}

class CatDefinition : AnimalDefinition
{
    public MeowSound Meow;
}

class Animal<TDefinition> where TDefinition : AnimalDefinition
{
    public TDefinition Definition;

    public void Jump()
    {
        Console.WriteLine("Jump.");
    }
}

class Dog : Animal<DogDefinition> 
{
    public Dog(DogDefinition def)
    {
        Definition = def;
    }
}

class Cat : Animal<CatDefinition> 
{
    public Cat(CatDefinition def)
    {
        Definition = def;
    }
}

class Trainer
{
    Animal _animal;

    public Trainer(Animal myAnimal)
    {
        _animal = myAnimal;
    }

    public MakeJump()
    {
        _animal.Jump();
    }

    public Listen()
    {
         // if T is DogDefinition hear barking
         // else if T is CatDefinition hear a meowing, etc
    }
}

      

EDIT: Additional question after Chris Berger's answer (which works, but I didn't change the code to make the question / answer logic logical). I added a definition member to the Animal class. Is there any way to access Bark or Meow from the Trainer class or will I need to inherit from the Trainer class with CatTrainer : Trainer<CatDefinition>

? That is, there is something similar to what we have with classes,

if(T is CatDefinition)
{ // Meowing} 
else 
{}

      

+3


source to share


1 answer


I think I agree with the first commenter that you don't necessarily need generics for this, but assuming you have another reason for getting generics ...

The solution here is to create the Animal class, which Animal <T> derives from.

For example:

public class Animal 
{ 
    public virtual void Jump()
    {   
        Console.WriteLine("Jump.");
    }               
}

public class Animal<T> : Animal where T : AnimalDefinition
{
     public override void Jump() 
     {
        //you can override Jump here if you want to
     }
}

public class Dog : Animal<DogDefinition>  {}
public class Cat : Animal<CatDefinition>  {}

      

Or, secondly, the second option is to give Trainer visibility for the general parameter:



public class Animal<T> where T : AnimalDefinition
{
     public void Jump() 
     {
         Console.WriteLine("Jump.");
     }
}

public class Dog : Animal<DogDefinition>  {}
public class Cat : Animal<CatDefinition>  {}

public class Trainer<T> where T : AnimalDefinition
{
    Animal<T> _animal;

    public Trainer(Animal<T> myAnimal)
    {
        _animal = myAnimal;
    }

    public MakeJump()
    {
        _animal.Jump();
    }
}

      

And as a tangent ... it might be a good place to use the self-referential general.

public class Animal<T> where T : Animal<T> { }
public class Dog : Animal<Dog> { }

      

Here's a bit more reading on this pattern: https://blogs.msdn.microsoft.com/simonince/2008/06/12/generics-the-self-referencing-generics-pattern/

+2


source







All Articles