C#中的多态性
     原文地址:wwwblogs/zhangkai2237/archive/2012/12/20/2826734.html
 
相信大家都对面向对象的三个特征封装、继承、多态很熟悉,每个人都能说上一两句,但是大多数都仅仅是知道这些是什么,不知道CLR内部是如何实现的,所以本篇文章主要说说多态性中的一些概念已经内部实现的机理。
       
一、多态的概念
        首先解释下什么叫多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是多态性。换句话说,实际上就是同一个类型的实例调用“相同”的方法,产生的结果是不同的。这里的“相同”打上双引号是因为这里的相同的方法仅仅是看上去相同的方法,实际上它们调用的方法是不同的。 
 
        说到多态,我们不能免俗的提到下面几个概念:重载、重写、虚方法、抽象方法以及隐藏方法。下面就来一一介绍他们的概念。
        1、重载(overload):在同一个作用域(一般指一个类)的两个或多个方法函数名相同,参数列表不同的方法叫做重载,它们有三个特点(俗称两必须一可以):
方法名必须相同
参数列表必须不相同
返回值类型可以不相同
        如:
        public void Sleep()
        {
            Console.WriteLine("Animal睡觉");
        }
        public int Sleep(int time)
        {
            Console.WriteLine("Animal{0}点睡觉", time);
            return time;
        }
 
        2、重写(override):子类中为满足自己的需要来重复定义某个方法的不同实现,需要用override关键字,被重写的方法必须是虚方法,用的是virtual关键字。它的特点是(三个相同):
相同的方法名
相同的参数列表
相同的返回值。
如:父类中的定义:
        public virtual void EatFood()
        {
            Console.WriteLine("Animal吃东西");
        }


       子类中的定义:
        public override void EatFood()
        {
            Console.WriteLine("Cat吃东西");
            //base.EatFood();
        }
tips:经常有童鞋问重载和重写的区别,而且网络上把这两个的区别作为C#做常考的面试题之一。实际上这两个概念完全没有关系,仅仅都带有一个“重”字。他们没有在一起比较的意义,仅仅分辨它们不同的定义就好了。
       
        3、虚方法:即为基类中定义的允许在派生类中重写的方法,使用virtual关键字定义。如:
        public virtual void EatFood()
        {
            Console.WriteLine("Animal吃东西");
        }
 
        注意:虚方法也可以被直接调用。如:
            Animal a = new Animal();
            a.EatFood();
 
        运行结果:
               
 
        4、抽象方法:在基类中定义的并且必须在派生类中重写的方法,使用abstract关键字定义。如:
    public abstract class Biology
    {
        public abstract void Live();
    }
    public class Animal : Biology
    {
        public override void Live()
        {
            Console.WriteLine("Animal重写的抽象方法");
            //throw new NotImplementedException();
        }
    }
 
 
        注意:抽象方法只能在抽象类中定义,如果不在抽象类中定义,则会报出如下错误:     
            
 
虚方法和抽象方法的区别是:因为抽象类无法实例化,所以抽象方法没有办法被调用,也就是说抽象方法永远不可能被实现。
 
        5、隐藏方法:在派生类中定义的和基类中的某个方法同名的方法,使用new关键字定义。如在基类Animal中有一方法Sleep():
        public void Sleep()
        {
            Console.WriteLine("Animal Sleep");
        }
 
            则在派生类Cat中定义隐藏方法的代码为:
        new public void Sleep()
        {
            Console.WriteLine("Cat Sleep");
        }
 
            或者为:
        public new void Sleep()
        {
            Console.WriteLine("Cat Sleep");
        }   
 
        注意:(1)隐藏方法不但可以隐藏基类中的虚方法,而且也可以隐藏基类中的非虚方法。
                  (2)隐藏方法中父类的实例调用父类的方法,子类的实例调用子类的方法。
                  (3)和上一条对比:重写方法中子类的变量调用子类重写的方法,父类的变量要看这个父类引用的是子类的实例还是本身的实例,如果引用的是父类的实例那么调用基类的方法,如果引用的是派生类的实例则调用派生类的方法。
 
        好了,基本概念讲完了,下面来看一个例子,首先我们新建几个类:
    public abstract class Biology
    {
        public abstract void Live();
    }
    public class Animal : Biology
    {
        public override void Live()
        {
            Console.WriteLine("Animal重写的Live");
            //throw new NotImplementedException();
        }
        public void Sleep()
        {
            Console.WriteLine("Animal Sleep");
        }
        public int Sleep(int time)
        {
            Console.WriteLine("Animal在{0}点Sleep", time);
            return time;
        }
        public virtual void EatFood()
        {
            Console.WriteLine("Animal EatFood");
        }
    }
    public class Cat : Animal
    {
        public override void EatFood()
        {
            Console.WriteLine("Cat EatFood");
            //base.EatFood();
        }
        new public void Sleep()
        {
            Console.WriteLine("Cat Sleep");
        }
        //public new void Sleep()
        //{
        //    Console.WriteLine("Cat Sleep");
        //}
    }
    public class Dog : Animal
    {
        public override void EatFood()
        {
            Console.WriteLine("Dog EatFood");
            //base.EatFood();
        }
    }
 
 
        下面来看看需要执行的代码:
    class Program
    {
        static void Main(string[] args)
        {
            //Animal的实例
            Animal a = new Animal();
            //Animal的实例,引用派生类Cat对象
            Animal ac = new Cat();
            //Animal的实例,引用派生类Dog对象
            Animal ad = new Dog();
writeline特点            //Cat的实例
            Cat c = new Cat();
            //Dog的实例
            Dog d = new Dog();
            //重载
            a.Sleep();
            a.Sleep(23);

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。