标题可能不清楚,但请查看下面的模式
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;
}
答案 0 :(得分: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>
{
}
你这样称呼:
var cat = new Cat();
var dog = new Dog();
var giraffe = new Giraffe();
Cat cat2 = cat.GetAnimal;
Dog dog2 = dog.GetAnimal;
Giraffe giraffe2 = giraffe.GetAnimal;
答案 1 :(得分:6)
调用方法将检查返回实例的类型并相应地使用它。
有你的问题。这需要代码气味。你应该能够把它只是一个对象,而不是以不同的方式对待狗和猫。
如果您需要显示任一动物的内容,请覆盖两个类的ToString
方法,然后在动物上调用ToString
。如果您需要知道狗或猫的名字,请将Name
属性添加到Animal
。如果可能的话,你应该在这里使用多态,这样任何使用该对象的东西都只是Animal
,并且由于同一方法的不同实现而简单地涉及不同的事情。
如果您确实需要知道Animal
是Dog
还是Cat
,那么您可以使用is
或as
运营商;您不需要添加您在OP中显示的所有代码。
答案 2 :(得分:5)
更好的方法是使用单一方法。
public abstract Animal getAnimal();
任何派生类都将知道如何返回自己。我希望这是有道理的。但是我不认为你会想要归还动物。没有意义。
Animal dog = new Dog() ;
dog.getAnimal();
困惑吧?
你可以有一个动物/列表数组,遍历集合并检查如下:
if(animal is Dog)
但是你还在检查类型。如果你想使用一个基类,那么它就有意义并暴露一个常用的方法。
答案 3 :(得分:1)
这是一个非常简洁的设计,因为它违反了Open-Closed principle。您希望您的类可以打开以进行扩展,但不能修改。 如果明天你想要添加另一个课程会怎么样?
public class Donkey : Animal
{
}
您必须更改基类,以便它具有属性GetDonkey
。
您还必须更改使用您的课程的所有课程并添加if (animal.GetDonkey == null)
你应该做的是使用这样的工厂设计模式:
public static class AnimalFactory
{
public static Dog GetDog()
{
return new Dog();
}
public static Cat GetCat()
{
return new Cat();
}
}
或者你应该使用像@Lews Therin建议的虚拟方法。
答案 4 :(得分:-2)
拥有只返回被调用对象的属性似乎没什么用处。
也许你只是在寻找一种从超类向子类转发的方法?如果是这样,只需使用强制转换:
Animal a = new Cat();
try
{
Dog d = (Dog)a;
}
catch (InvalidCastException)
{
try
{
Cat c = (Cat)a;
}
catch (InvalidCastException)
{
}
}