在类层次结构中向后扩展多态性





3.00/5 (2投票s)
本文解释了如何将多态行为应用回类层次结构。
引言
本文解释了如何在类层次结构中向后应用多态行为。
Using the Code
本文使用 Visual Studio 2008。
问题
您可能希望将多态行为应用于继承自相同基类的不同级别的类的对象,而这些类没有共同的接口。例如,假设您有一个从同一基类继承而来的不同类型对象的数组。您希望为数组中的所有对象调用一个方法,但该方法仅存在于其中一个继承类中。
最合理的方法是将该方法移动到层次结构中(并在需要时使其成为虚拟方法)。但是,这并不总是由您掌控的——基类可能位于第三方库中,或者由于其他原因而无法访问。
解决方案
使用扩展方法将允许您完成此操作。以下是示例。
创建一个名为 Animal
的基类。假设这是您无法访问的类,并且您无法修改它。
public abstract class Animal
{
}
创建一个继承类 DomesticAnimal
,该类引入了方法 Says()
。这是您希望在从 Animal
继承的所有类中调用的方法。
public class DomesticAnimal : Animal
{
public virtual string Says()
{
return null;
}
}
创建从 DomesticAnimal
继承并实现方法 Says()
的类 Cat
和 Dog
。
public class Cat : DomesticAnimal
{
public override string Says()
{
return "Meow!";
}
}
public class Dog : DomesticAnimal
{
public override string Says()
{
return "Woof!";
}
}
创建一个直接从 Animal
继承的类 Wolf
,因此它没有 Says()
方法。
public class Wolf: Animal
{
}
现在,想象一个客户端代码,它创建了上述 Animal
对象的数组,并希望在数组中的每个对象上调用 Says()
方法,包括 Wolf
。
static void Main(string[] args)
{
Animal[] animals = new Animal[3];
animals[0] = new Cat();
animals[1] = new Dog();
animals[2] = new Wolf();
foreach (Animal animal in animals)
{
Console.WriteLine("{0} says {1}",
animal.GetType().Name, animal.Says());
}
}
当然,这段代码将无法编译。将显示以下错误,指向 Animal.Says()
方法
'BackwardPolymorphism.Animal' does not contain a definition for 'Says'
and no extension method 'Says' accepting a first argument of type
'BackwardPolymorphism.Animal' could be found
(are you missing a using directive or an assembly reference?)
现在,让我们添加一个新的 static
类,该类将为 Animal
类提供一个扩展方法 Says()
(请注意扩展方法和继承方法的名称相同)。我们必须动态检查对象类型并转换对象,以便调用继承类的内部 Says()
方法。
public static class AnimalExtension
{
public static string Says(this Animal animal)
{
string says = "[Unknown]";
if (animal is DomesticAnimal)
{
says = ((DomesticAnimal)animal).Says();
}
return says;
}
}
现在代码将编译。运行时,它会产生以下输出

历史
- 2009 年 6 月 19 日:初始版本