在.NET中,多态通常意味着子类对于父类一种衍变。子类继承自父类,拥有父类所定义的一切(public或protected)成员。但同时,它又可以修改(重写或复写)这些成员,使其实现与父类以及其他子类完全不同。我们可以说,继承体现了类的多态性。
大家应该很熟悉Duck的例子了吧?
public abstract class Duck
{
public abstract void Quack();
}
public class MallardDuck : Duck
{
public override void Quack()
{
Console.WriteLine("Quack, quack, quack...");
}
}
public class RubberDuck : Duck
{
public override void Quack()
{
Console.WriteLine("Squeak, squeak, squeak...");
}
}
public class Program
{
public static void Main()
{
Duck duck = new MallardDuck();
duck.Quack();
duck = new RubberDuck();
duck.Quack();
Console.ReadLine();
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
MallardDuck和RubberDuck虽然都继承自抽象类Duck,同样拥有Quack()方法,但它们却有不同的实现,产生不同的结果。在声明Duck类型时,既可以实例化为Mallard,也可以实例化为RubberDuck,或者是其他继承自Duck的类,在运行时,将自动调用各个子类的实现。
多态的这些特性使依赖注入和面向抽象编程成为可能,其重要性不言而喻。
不一样的多态
然而,既然多态是指同一类事物之间的不同形态,那么我们为什么要把对于多态的理解局限于类的继承关系呢?在.NET中是否还存在着非继承关系的多态性呢?
泛型体现了参数的多态性
类型参数在泛型中通常解释为占位符,而我更愿意将其理解为对参数的一种抽象。以最常见的List
public class MyList<T>
{
private T[] items;
private int size;
public void Add(T item)
{
if (size == items.Length)
{
// modify capacity
}
items[size++] = item;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
如果我们使用MyList
您是否也觉得这是多态性的一种体现呢?
再来看看十分经典的Swap
public class Swapper
{
private static void Swap<T>(ref T o1, ref T o2)
{
T temp = o1;
o1 = o2;
o2 = temp;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
Swap
委托体现了方法的多态性
委托是对拥有相同参数和返回值的所有方法的封装。只要方法拥有同样的参数列表和返回值,委托都认为它们属于同一“类型”的方法,可以添加到同一个委托链表中。
public delegate void FooDelegate(List<string> list, string str);
public class DelegateTest
{
public void AddToList(List<string> list, string strToAdd)
{
list.Add(strToAdd);
}
public static void PrintIfContains(List<string> list, string strToCheck)
{
if (list.Contains(strToCheck))
Console.WriteLine("The list contains " + strToCheck);
}
}
public class Program
{
public static void Main()
{
List<string> list = new List<string>();
list.Add("Kirin");
DelegateTest delegateTest = new DelegateTest();
FooDelegate fooDelegate = new FooDelegate(delegateTest.AddToList);
fooDelegate += new FooDelegate(DelegateTest.PrintIfContains);
fooDelegate(list, "麒麟.NET");
Console.ReadLine();
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
在上例中,FooDelegate委托封装了参数为List
您是否也认为这是方法的多态性的一种体现呢?
多态小结
我们通常所讨论的多态,就是指子类对父类方法的重写(虚方法)或覆盖(非虚方法),这样的理解未免过于狭隘。.NET强大的特性能够实现其他语言中无法实现的多态性。如本文所列举的泛型和委托。您是否认同笔者的观点呢?如果认同,您是否还能举出其他的例子呢?
您可能觉得本文缺乏技术含量。的确是的,本文并不包含多么高深的技术和思想,而只是笔者最近学习过程中一些琐碎的领悟。如果能够帮助到您,将是笔者的荣幸。
【编辑推荐】