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驴子(),而是您自己