Abstract method with strongly typed inverse type

Consider the following classes:

public abstract class Animal
{
    public abstract Animal GiveBirth();
}

public class Monkey : Animal
{
    public override Animal GiveBirth()
    {
        return new Monkey();
    }
}

public class Snake : Animal
{
    public override Animal GiveBirth()
    {
        return new Snake();
    }
}

//That one doesnt makes sense.
public class WeirdHuman: Animal
{
    public override Animal GiveBirth()
    {
        return new Monkey();
    }
}

I am looking for a way to force the return types of an overridden method GiveBirthso that it always returns the actual type of the class, so no WeirdHumancan give birth Monkey.

It seems to me that the answer is about generic types, but I do not see how I can do this.

An example of the expected result:

public abstract class Animal
{
    public abstract /*here a way to specify concrete type*/ GiveBirth();
}

public class Monkey : Animal
{
    public override Monkey GiveBirth() //Must returns an actual Monkey
    {
        return new Monkey();
    }
}

“Absolutely impossible” may be the answer, if clearly explained.

+5
source share
3 answers

#. . , , , - , , .

public abstract class Animal<TBirthType> where TBirthType : Animal<TBirthType>
{
    public abstract TBirthType GiveBirth();
}

public class Monkey<TBirthType> : Animal<TBirthType> where TBirthType : Monkey<TBirthType>
{
    public override TBirthType GiveBirth()
    {
        return new Monkey<Monkey>();
    }
}

, , .

public class Monkey : Animal<Monkey>
{
    public override Monkey GiveBirth()
    {
        return new Monkey();
    }
}

, - , , , . , - . , , , , .

+5

- , Animal<T> Animal<T> GiveBirth(), , , .

, , :

public abstract class Animal<T> where T: Animal<T>
{
    public abstract Animal<T> GiveBirth();
}

public class Monkey: Animal<Monkey>
{
    public override Animal<Monkey> GiveBirth()
    {
        return new Monkey();
    }
}

public class Snake: Animal<Snake>
{
    public override Animal<Snake> GiveBirth()
    {
        return new Snake();
    }
}

public class WeirdHuman: Animal<WeirdHuman>
{
    public override Animal<WeirdHuman> GiveBirth()
    {
        return new Monkey(); // Won't compile of course.
    }
}

public override Animal<Monkey> GiveBirth(), , - :

1 'ConsoleApplication1.Monkey' 'ConsoleApplication1.Animal.GiveBirth()'

, SomeKindOfAnimal: Animal<SomeKindOfAnimal>, , , .

( . .)

, , :

public class Monkey: Animal<WeirdHuman>
{
    public override Animal<WeirdHuman> GiveBirth()
    {
        return new WeirdHuman();
    }
}

, , GiveBirth() , ; . , , , .

, , .

+1

, . ,

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

, ,

public class WierdHuman<Monkey> { }

, , - Haskell typeclasses, . , #, - , , , .

.

, , typeclass. :

public interface ISpawn<T> where T : Animal
{
    public T GiveBirth();
}

public void Populate<T>(T parent, ISpawn<T> spawn) where T : Animal
{
}
+1
source

All Articles