当你想要一个不关心具体实现而只关心总体类型的通用方法时,多态真的派上用场了。以你的动物为例:
public static void Main()
{
var animals = new List<Animal>();
animals.Add(new Dog());
animals.Add(new Cat());
foreach (var animal in animals)
Feed(animal);
}
public static void Feed(Animal animal)
{
animal.Eat();
}
请注意,该方法并不关心它得到什么样的动物,它只是试图喂它。也许Dog 实现了Eat() 以至于它吞噬了所有可见的东西。也许Cat() 实现了它,让它咬一口然后走开。也许Fish() 实现它以至于它吃得太多而死。该方法本身并不关心它得到哪个Animal,您可以轻松添加更多Animal 类型,而无需更改接受它们的方法。
(与此相关的是Strategy Pattern。)
相反,有时您希望方法返回通用类型,而不管实现了什么。我使用的一个常见示例是:
public interface AnimalRepository
{
IEnumerable<Animal> GetAnimals();
}
这实际上以两种方式使用多态性。首先,它返回的Animals 的枚举可以是任何类型。在这种情况下,任何调用代码都不会关心哪个是哪个,它将以更一般的方式使用它们(例如在前面的示例中)。此外,任何实现IEnumerable 的东西都可以返回。
例如,我有一个使用 LINQ to SQL 的接口实现:
public class AnimalRepositoryImplementation : AnimalRepository
{
public IEnumerable<Animal> GetAnimals()
{
return new DBContext().Animals;
}
}
这将返回一个IQueryable。然而,无论调用该方法,都不关心它是一个IQueryable。它只会使用IEnumerable 上的功能。
或者,我有另一个模拟测试的实现:
public class AnimalRepositoryImplementation : AnimalRepository
{
private IList<Animal> animals = new List<Animal>();
public IEnumerable<Animal> GetAnimals()
{
return animals;
}
}
这将返回一个IList,它再次被变形为更通用的IEnumerable,因为这就是调用代码将要使用的全部内容。
这些也称为covariance and contravariance。在返回上面的IEnumerable 的情况下,类型从更具体的(IQueryable 和IList)移动到更通用的(IEnumerable)。他们无需转换就能做到这一点,因为更具体的类型也是类型层次结构中更通用类型的实例。
与此相关的还有Liskov Substitution Principle,它指出类型的任何子类型都可以用作该父类型,而无需更改程序。也就是说,如果Dog 是Animal 的子类型,那么您应该始终能够将Dog 用作Animal,而不必知道它是Dog 或做任何特殊的考虑。
您还可以从查看Dependency Inversion Principle 中受益,上面的存储库实现可以作为示例。正在运行的应用程序不关心哪种类型 (AnimalRepositoryImplementation) 实现了该接口。它关心的唯一类型是接口本身。实现类型可能具有额外的公共或至少内部方法,实现程序集使用这些方法来确定特定依赖项是如何实现的,但这对使用代码没有影响。每个实现都可以随意换出,调用代码只需提供更通用接口的任何实例。
旁注: 我个人发现继承经常被过度使用,尤其是像Animal 示例中的普通继承,其中Animal 本身不应该是可实例化的类。如果应用程序的逻辑需要通用形式,它可能是接口或抽象类。但不要只是为了做而做。
一般而言,更喜欢Gang Of Four book 推荐的composition over inheritance。 (如果您没有副本,请获取一份。)不要过度使用继承,但要在适当的地方使用它。如果将常见的Animal 功能分组到组件中并且每个Animal 都是由这些组件构建的,那么应用程序可能会更有意义?当然,更常用的Car 示例可以从中吸取教训。
保持类型的逻辑定义。你应该可以写new Animal()吗?拥有一个不再具体的Animal 的通用实例是否有意义?当然不是。但是拥有应该能够在任何Animal 上运行的通用功能(馈送、复制、死亡等)可能是有意义的。