首页 > 代码库 > 面向对象---多态

面向对象---多态

  最新QQ弹窗弹了个腾讯课堂的推广消息,就点进去看了。里面琳琅满目,有着各种方面的免费基础教学。好奇心驱使,报名了一个.net的基础课堂,并加了群。群里很多都是在校学生和初学开发的朋友。看到他们和我初学时一样,对多态的理解很模糊,所以想写此博文。一来把自己的理解共享给大家,二来可以巩固自己所学,此为背景。

  让我们先来看看多态到底能够给我们带来什么好处。

  以一个飞机控制系统,需要让所有的飞机都可以飞起来。这是最容易想到的写法:

    /// <summary>    /// 所有飞机的基类    /// </summary>    public class PlaneBase    {        public static PlaneBase GetPlane(string planeName)        {            switch(planeName)            {                case "喷气机":                    return new Jet();                case "直升机":                    return new Copter();            }            return null;        }        /// <summary>        /// 起飞        /// </summary>        public void Fly()        {            Console.WriteLine("起飞了!");        }    }
所有飞机的父类
    /// <summary>    /// 喷气机    /// </summary>    public class Jet : PlaneBase    {    }
喷气机
    /// <summary>    /// 直升机    /// </summary>    public class Copter : PlaneBase    {    }
直升机 
           static void Main(string[] args)        {            PlaneBase jet = PlaneBase.GetPlane("喷气机");            jet.Fly();            PlaneBase copter = PlaneBase.GetPlane("直升机");            copter.Fly();        }
控制飞机起飞

  我们利用了继承的特性,通过一个父类,让所有子类都自动具有了起飞的方法。

  但是我们很快发现了问题,直升机和喷气机的起飞方式不一样啊,喷气机是向前加速起飞的,直升机是直上的。

  于是我们修改我们的代码,在子类分别实现自己的起飞方法:

    /// <summary>    /// 喷气机    /// </summary>    public class Jet : PlaneBase    {        public void Fly()        {            Console.WriteLine("喷气机起飞了!");        }    }
喷气机
    /// <summary>    /// 直升机    /// </summary>    public class Copter : PlaneBase    {        public void Fly()        {            Console.WriteLine("直升机起飞了!");        }    }
直升机
        static void Main(string[] args)        {            Jet jet = new Jet();            jet.Fly();  //喷气机起飞            Copter copter = new Copter();            copter.Fly();   //直升机起飞        }
控制飞机起飞

  再次调试,哈,这次成功了,直升机和喷气机都按照自己的起飞方式起飞了。

  可是问题又来了,仔细对比两次控制飞机飞行的代码,发现区别了吗?

  我们控制的时候,不得不事先知道这是个什么样的飞机(具体的飞机对象),再去控制它起飞;这一定是控制者的恶梦。

  多态的强大之处就在此体现出来了,先来看看修改后的代码。

   /// <summary>    /// 所有飞机的基类    /// </summary>    public class PlaneBase    {        public static PlaneBase GetPlane(string planeName)        {            switch(planeName)            {                case "喷气机":                    return new Jet();                case "直升机":                    return new Copter();            }            return null;        }        /// <summary>        /// 起飞        /// </summary>        public virtual void Fly()        {            Console.WriteLine("起飞了!");        }    }
所有飞机的父类
    /// <summary>    /// 喷气机    /// </summary>    public class Jet : PlaneBase    {        public override void Fly()        {            Console.WriteLine("喷气机起飞了!");        }    }
喷气机
    /// <summary>    /// 直升机    /// </summary>    public class Copter : PlaneBase    {        public override void Fly()        {            Console.WriteLine("直升机起飞了!");        }    }
直升机
        static void Main(string[] args)        {            PlaneBase jet = PlaneBase.GetPlane("喷气机");            jet.Fly();            PlaneBase copter = PlaneBase.GetPlane("直升机");            copter.Fly();            Console.ReadLine();        }
控制飞机起飞

  我们在父类的Fly方法前加上了virtual关键字,将它标识为一个虚方法,然后在子类的Fly方法前加上了override关键字,意味着覆盖父类的方法(重写)。

  现在,我们的控制者只需要获取一个飞机(PlaneBase.GetPlane方法),并不需要关心获取到的到底是直升机还是喷气机,只要让它起飞(调用Fly方法),飞机就会按照自己的的起飞方式起飞了(程序自动调用对应子类的Fly方法)。

  就这样简单,但好处却是显而易见。

 

  如何实现多态?

  1. 存在一个继承体系结构。如果不存在继承体系结构,那么所谓的多态就无从谈起。

  2. 把我们需要的统一的接口(方法)在父类中定义,并标记为虚方法。

  3. 子类重写该方法。

  这只是多态最最基本的一种实现,也是用得最多的。

 

  那我们在什么时候需要用到多态呢?

  简单来说就是,当接口确定,而在不同环境中需要不同实现的时候,我们就要用到多态了。比如操作数据库的时候,我们只需要使用数据库父对象,调用一个统一的接口,就可以使用增删改查,不需要关心数据库到底是Sqlserver还是oracle,真正的数据库操作放到对应数据库的子类去实现;

  

  

  

面向对象---多态