Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从基类返回派生类实例_C#_Inheritance - Fatal编程技术网

C# 从基类返回派生类实例

C# 从基类返回派生类实例,c#,inheritance,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 overri

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

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

}
在基类、返回派生类型中具有属性被认为是一种不好的做法。或者我应该做类似的事情

public abstract AnimalTypeEnum AnimalType { get; }
编辑:根据这些评论,我想我应该更清楚我想要实现什么。
Dog
Cat
类的新实例将由一个单独的函数基于某些条件创建,然后将
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;

}

不,你做错了

最好有一个单一的方法

public abstract Animal getAnimal();
任何派生类都将知道如何返回自身。我希望这是有道理的。但我认为你也不会想要归还动物。没有道理

Animal dog = new Dog() ;
dog.getAnimal(); 
困惑是吧

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

if(animal is Dog)

但你仍然在检查类型。如果您想使用基类,请使用它,使其有意义并公开一个公共方法。

让属性只返回调用它们的对象似乎不是很有用

也许你只是在寻找一种从超类向下转换为子类的方法?如果是这样,只需使用强制类型转换:

Animal a = new Cat();

try
{
    Dog d = (Dog)a;
}
catch (InvalidCastException)
{
    try
    {
        Cat c = (Cat)a;
    }
    catch (InvalidCastException)
    {
    }
}

这是一个真正的bas设计,因为它违反了。您希望您的类开放以进行扩展,但关闭以进行修改。 如果明天你想再增加一门课,会发生什么

public class Donkey : Animal
{
}
您必须去更改基类,使其具有一个属性
getassy
。 您还必须更改使用您的类的所有类,并添加
if(animal.get驴==null)

您应该使用以下factory设计模式:

public static class AnimalFactory
{
  public static Dog GetDog()
  {
    return new Dog();
  }

  public static Cat GetCat()
  {
    return new Cat();
  }
}
或者您应该使用建议的虚拟方法

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

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;

}
这是你的问题。这是我们需要做的。你应该能够把任何东西当作一个物体来对待,而不是区别对待猫和狗

如果需要显示任一动物的内容,则在两个类上重写
ToString
方法,只需在动物上调用
ToString
。如果您需要知道狗或猫的名称,请将
名称
属性添加到
动物
。如果可能的话,您应该在这里使用多态性,这样无论使用对象的是什么,它都会像动物一样对待对象,只会因为同一方法的不同实现而涉及到不同的事情


如果您确实需要知道
动物
还是
,那么您可以使用
还是
作为操作员;您不需要添加操作中显示的所有代码。

如果您只想要从中获得的动物,可以执行以下操作:

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

你这样做的最终目的是什么?@user1556110这并没有真正回答这个问题。这些方法将如何实际使用?好的。。。但这有什么意义呢?狗不应该有办法得到猫,即使它返回空值。
Animal dog=new dog()
有什么问题吗?我会从一个函数返回基类,然后调用该函数的方法将其转换为相关的派生类型。在我看来,您似乎在尝试为
dog dog=Animal as dog提供一种替代语法。一般来说,您应该避免基类知道派生类——否则要添加新的派生类,您必须更改基类——这相当混乱。您不应该对控制流使用异常
因为
被设计为在不产生异常的情况下执行此操作。同意@Servy的观点,这是一个糟糕的设计。但是,现在您可以利用switch语句模式匹配在函数中实现一些非常类似的功能(没有所有try/catch的废话)。调用
CreateAnimal
函数时,需要动态创建
Cat
类型或
Dog
类型,并且无法知道需要先创建哪种类型。所以我真的需要返回最小保证类型,如果他们想多做一点,还需要提供选项。@user1556110是的,
CreateAnimal
方法很好;我不是建议你改变它。我的意思是,您应该能够对返回的
动物
执行任何需要执行的操作,而不必执行导致
实例的操作。虽然可能有一种情况下,你真的不能这样做,你应该非常肯定,然后再走这条路。如果你真的这样做了,就像我说的,你应该使用
is
as
而不是你创建的结构。@user1556110-即使假设你需要知道它是猫还是狗,你可以用
is
@bobson替换你想用的任何测试。我同意
is
部分,我不一定需要知道它是
猫还是
狗来调用
动物的方法,而我需要知道调用派生类型上某些方法的类型,否则这些派生类型对其他类型无效。还有其他方法吗?@user1556110如果您需要一个只用于cat的
LookCute
方法,那么您不应该对从方法返回的对象调用它,该方法可能是cat,也可能不是cat。您应该只调用
LookCute
,从一开始,您就知道可以让它看起来很可爱。您提到不应该有一个get驴子(),而是您自己