从基类返回派生类实例

swi*_*tgp 7 c# inheritance

标题可能不清楚,但请看下面的模式

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; }
    }

}
Run Code Online (Sandbox Code Playgroud)

这被认为是在基类中具有属性,返回派生类型的不良做法.或者我应该做些什么

public abstract AnimalTypeEnum AnimalType { get; }
Run Code Online (Sandbox Code Playgroud)

编辑:根据评论,我想我应该更清楚我想要实现的目标.该类DogCat类的新实例将由基于特定条件的单独函数创建,然后将Animal类型返回给调用者.调用方法将检查返回实例的类型并相应地使用它.

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;

}
Run Code Online (Sandbox Code Playgroud)

Ale*_*man 12

如果你只想要你从中获得的动物可以这样做:

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>
{
}
Run Code Online (Sandbox Code Playgroud)

你这样称呼:

var cat = new Cat();
var dog = new Dog();
var giraffe = new Giraffe();
Cat cat2 = cat.GetAnimal;
Dog dog2 = dog.GetAnimal;
Giraffe giraffe2 = giraffe.GetAnimal;
Run Code Online (Sandbox Code Playgroud)


Ser*_*rvy 7

调用方法将检查返回实例的类型并相应地使用它.

这是你的问题.这需要代码气味.你应该能够把它只是一个对象,而不是以不同的方式对待狗和猫.

如果你需要显示任何一种动物的内容,那么ToString在两个类上重写方法,然后只需要调用ToString动物.如果你需要知道狗或猫的名字,那么添加一个Name属性Animal.如果你可能的话,你应该在这里使用多态,这样任何使用该对象的东西都只是一个Animal简单地涉及不同的事情,因为同一方法的不同实现.

如果你真的,确实需要知道Animal是a Dog还是a Cat那么你可以使用isas运算符; 您不需要添加您在OP中显示的所有代码.

  • @ user1556110如果你只需要一个只有猫的`LookCute`方法,那么你不应该在一个可能会或可能不是猫的方法返回的对象上调用它.你应该只在一些东西上调用`LookCute`,从一开始,你就知道它看起来很可爱. (2认同)

Lew*_*rin 5

不,你做错了.

更好的方法是使用单一方法.

public abstract Animal getAnimal();
Run Code Online (Sandbox Code Playgroud)

任何派生类都将知道如何返回自己.我希望这是有道理的.但是我不认为你会想要归还动物.没有意义.

Animal dog = new Dog() ;
dog.getAnimal(); 
Run Code Online (Sandbox Code Playgroud)

混淆吧?

你可以有一个动物/列表数组,遍历集合并检查如下:

if(animal is Dog)
Run Code Online (Sandbox Code Playgroud)

但你还在检查类型.如果你想使用一个基类让它有意义并暴露一个常见的方法.