【发布时间】:2010-01-18 16:03:35
【问题描述】:
我正在使用一个较小的类型层次结构,如下所示,并且可以说在我悲伤的无野生动物园世界中永远不会有任何其他动物类型(我一点也不担心扩展的弹性):
public abstract class Animal {};
public sealed class Dog : Animal {};
public sealed class Cat : Animal {};
public sealed class Turtle : Animal {};
public sealed class Bird : Animal {};
就 API 而言,我想以同样的方式对待所有动物,但显然它们在以下情况下的反应略有不同:
public class AnimalCare {
public void Feed<T> (T pet) where T: Animal;
public T PickUp<T> (PetStore store);
}
起初,在不将 feed 方法放在 Animal 类上的情况下执行喂养的想法(对不起,我知道这个例子已经到了这一点,但是为了争论,我们假设 AnimalCare 是我的 Animal 模型的视图我非常坚持关注点分离)会建议访问者。但我真正想做的是让上述成为 AnimalCare 的 API 消费者唯一需要担心的类型,而我执行以下操作:
public class AnimalCare {
public void Feed<T> (T pet) where T : Animal;
public T PickUp<T> (PetStore store);
public void Feed<Dog> (Dog rover)
{
// dump out alpo, lift toilet seat
}
public void Feed<Turtle> (Turtle franklin)
{
// do turtles eat? let him figure it out himself.
} // ...etc.
public Dog PickUp<Dog> (PetStore store)
{
// get bone, tennis ball, leash
}
public Bird PickUp<Bird> (PetStore store)
{
// make sure not dead, nailed to perch
} // ...etc.
}
等等。我知道第一部分(Feed () 方法)可以在不需要泛型的情况下重载,但这仍然给我留下了一个尴尬的 PickUp 实现(因为它不合法,正如我上面所描绘的那样),一些像 PickUpDog//PickUpBird 等悲惨的。我非常希望避免对 AnimalCare 的消费者及其志同道合的朋友有单独的“看法”。
我一直在尝试嵌套专门的类和其他奇怪的组合或接口重构尝试,但我似乎无法正确处理并陷入困境。有没有一种干净的方法来做我想做的事情,或者我是否愿意为每个具体的动物实施 AnimalCare?
编辑
Joel 关于工厂/存储库的观点让我想了更多。让我们将感兴趣的方法称为更合理一点:
public class AnimalPresentation {
public void Show (Dog dog);
public void Show (Cat cat);
//..etc.
public Animal Get (PetStore store);
}
我想这首先会更有意义。在调用 Get 时不知道要从 PetStore 中取出的 Animal 的类型,但是在 Get 的一般实现中,一旦确定了类型,它就会分支到特定的重载。 PetStore 的特定子类型是最佳/唯一的前进方式吗?
【问题讨论】:
标签: c# generics oop polymorphism