浅谈.NET中不一样的多态

开发 后端
多态(Polymorphism)一词源于生物学,顾名思义就是指多种形态。在面向对象世界里,多态与继承和封装一起构成了三大核心概念。本文将简单谈谈.NET中不一样的多态。

在.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为例,List和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,在内部就会声明一个字符串数组,Add方法的参数也必须为string。如果使用MyList,在内部就会声明一个int数组,Add方法的参数也必须为int。这看上去就像是T是string和int的“基类”,在使用MyList时(相当于客户端代码),T既可以是string也可以是int,或者是其他符合约束的类型,但在设计时,我们对这一切毫无所知。

您是否也觉得这是多态性的一种体现呢?

再来看看十分经典的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泛型方法就像是封装了N个非泛型的Swap方法,如Swap(ref int o1, ref int o2)、Swap(ref string o1, ref string o2)等等。在类型推断特性的支持下,您甚至可以像使用非泛型方法一样来使用泛型方法。参数T在某种程度上体现了不同的参数形态,因此我们有理由认为,泛型类型T体现了参数的多态性。

委托体现了方法的多态性

委托是对拥有相同参数和返回值的所有方法的封装。只要方法拥有同样的参数列表和返回值,委托都认为它们属于同一“类型”的方法,可以添加到同一个委托链表中。

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和string,并且没有返回值的方法。任何符合上述约束的方法,在FooDelegate中一视同仁。如,AddToList实例方法与PrintIfContains静态方法除了参数列表与返回值相同外,内部实现完全不同,但是它们却可以添加到同一个委托链表中。也就是说,同一个委托,可以定义并调用不同的方法(约束相同而实现不同)。

您是否也认为这是方法的多态性的一种体现呢?

多态小结

我们通常所讨论的多态,就是指子类对父类方法的重写(虚方法)或覆盖(非虚方法),这样的理解未免过于狭隘。.NET强大的特性能够实现其他语言中无法实现的多态性。如本文所列举的泛型和委托。您是否认同笔者的观点呢?如果认同,您是否还能举出其他的例子呢?

您可能觉得本文缺乏技术含量。的确是的,本文并不包含多么高深的技术和思想,而只是笔者最近学习过程中一些琐碎的领悟。如果能够帮助到您,将是笔者的荣幸。

【编辑推荐】

  1. ASP.NET开发程序过程中值得注意的两个地方
  2. 全面总结.NET 4.0新特性:C#和VB.NET的取长补短
  3. 深入理解Java多态性
  4. ASP.NET的错误处理机制
  5. 详解ASP.NET的四种状态
责任编辑:彭凡 来源: cnblogs
相关推荐

2012-03-07 17:24:10

戴尔咨询

2012-12-20 10:17:32

IT运维

2017-05-25 15:02:46

联宇益通SD-WAN

2015-10-19 12:33:01

华三/新IT

2016-05-09 18:40:26

VIP客户缉拿

2018-05-09 15:42:24

新零售

2009-12-01 16:42:27

Gentoo Linu

2009-02-04 15:43:45

敏捷开发PHPFleaPHP

2011-02-28 10:38:13

Windows 8

2016-03-24 18:51:40

2009-06-12 15:26:02

2009-01-20 10:39:00

Windows7IE 8浏览器

2019-01-03 14:39:08

Oracle甲骨文ORACLE

2022-05-05 21:47:32

Linuxls 命令

2015-08-25 09:52:36

云计算云计算产业云计算政策

2021-12-23 15:11:46

Web 3.0元宇宙Metaverse

2015-08-04 14:49:54

Discover

2013-01-11 18:10:56

软件

2011-03-14 16:51:24

2024-04-08 09:11:13

SVG前端CSS
点赞
收藏

51CTO技术栈公众号