一 多态的定义

     同一操作作用于不同的类的实例,不同的类将进行不同的解释,最后产生不同的执行结果。

 

二 多态的分类

    ● 编译时的多态性
    编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。
    ● 运行时的多态性
    运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。c#中,运行时的多态性通过虚成员实现。

 

三 多态的实现方式

     ● 接口实现多态。
     ● 继承实现多态。 
     ● 通过抽象类实现的多态。 

 

四 多态的实现方式举例

   

     ● 接口实现多态。    

/*
* 接口实现多态
* 一个公司有很多的门,但是不管什么门,都有开和关两种的状态。定义一个接口
* 定义两种类型的门door1,door2
* 公司为了验证其保安系统是否完好,检查公司2个门是否正常开和关。
*/

using System;
using System.Collections.Generic;
using System.Text;

namespace DoorApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            IDoor[] door = new IDoor[100];//定义一个接口数组
            for(int i=1;i<=2;i++)
            {
                if (i % 2==0)
                    door[i]=new door1();
                else
                    door[i]=new door2();
                door[i].Close();//接口实现方法的访问
                door[i].Open();
            }
           
        }
    }
    interface IDoor
    {
        void Open();
        void Close();
    }
    class door1:IDoor
    {
        private bool HavePerson=false;
         public void Open()
        {
            if(HavePerson)
            Console.WriteLine("door1门打开了");
        }

        public void Close()
        {
            if(!HavePerson)
            Console.WriteLine("door1门关上了");
        }   

    }
    class door2:IDoor
    {
        private bool isPassWord = false;
        public void Open()
        {
            if (isPassWord)
                Console.WriteLine("door2门打开了");
        }

        public void Close()
        {
            if (!isPassWord)
                Console.WriteLine("door2门关上了");
        }

    }
}

输出结果:

door1门关上了

door1门打开了

door2门关上了

door2门打开了

   

     ● 继承实现多态。

    

/*
* 继承实现多态
* 一个公司有很多的雇员,但是不管什么雇员,都工作。定义一个基类Employee定义了虚方法StaWork()

* 经理和销售继承基类并重写了基类的虚方法StaWork(),运行时通过基类引用继承类的实例达到调用子类的方法的目的*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    public class Employee
    {
        protected string _name;
        public Employee() { }
        public Employee(string name)
        {
            _name = name;
        }
        public virtual void StaWork()//虚方法
        {
            Console.WriteLine(_name+"开始工作:");
        }
    }
    class Manager : Employee
    {
        public Manager(string name) : base(name) { }
        public override void StaWork()//从重方法
        {
            base.StaWork();//调用父类的StaWork方法
            Console.WriteLine("给员工下达任务!");
        }
    }
    class Seller : Employee
    {
        public Seller(string name) : base(name) { }
        public override void StaWork()
        {
            base.StaWork();
            Console.WriteLine("销售产品!");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Employee[] emp = new Employee[3];
            emp[0] = new Manager("张三");
            emp[1] = new Seller("李四");
            emp[2] = new Seller("王五");
            Console.WriteLine("时间到了");
            foreach (Employee em in emp)
            {
                em.StaWork();
            }
        }  
    }
}

     父类的对象变量=new 子类类型,将子类对象赋值给父类对象,所得到对象是这样的一个对象,它是一个编译是为父类对象,但运行却是一个子类对象。具体特征如下:
    1.被声明为父类对象
  2.拥有父类属性
  3.占用子类的内存空间
  4.子类方法覆盖父类的方法时,此时对象调用的是子类的方法;否则,自动调用继承父类的方法.
  5.我人认为这个对象既不是父类对象,也不是子类对象.当我们用到它的方法时,
  我便把它看成子类对象;若用到它的属性时,我把它看成父类对象.它是一个占用父类属性,而使用子类方法的对象.至于到底是什么对象,我认为还是得根据声明来,它应算是父类对象,但拥有子类方法.

   

    ● 通过抽象类实现多态。 
     抽象类同时提供继承和接口的元素。抽象类本身不能实例化,他必须被继承。该类的部分或全部成员可能未实现,该实现由继承类提供。已实现的成员仍可被重写,并且继承类仍能实现附加接口或其他功能。抽象类提供继承和接口实现的功能。抽象类不能示例化,必须在继承类中实现。他能包含已实现的方法和属性,但也能包含未实现的过程,这些未实现过程必须在继承类中实现。这使你得以在类的某些方法中提供不变级功能,同时为其他过程保持灵活性选项打开。抽象类的另一个好处是:当需求组件的新版本时,可根据需要将附加方法添加到基类,但接口必须保持不变。

     /*定义一个抽象类VideoShow及其抽象方法 playVideo在定义两个DVD,VCD类继承并重写playVideo方法

       *然后利用抽象类playVideo引用DVD,VCD类实例来调用DVD,VCD类地方法达到多态的效果。

    */

using System;
using System.Collections.Generic;
using System.Text;

namespace Video
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            p.PlayVideo();
           
        }
        public void PlayVideo()
        {
            VideoShow vw;
            vw = new DVD();
            Console.WriteLine(vw.playVideo());
            vw = new VCD();
            Console.WriteLine(vw.playVideo());
        }
    }
    public abstract class VideoShow //不能被实例化
    {
        public abstract string playVideo();
    }
    public class VCD:VideoShow
    {
        public override string playVideo()
        {
            return "正在播放VCD";
        }

    }
    public class DVD : VideoShow
    {
        public override string playVideo()
        {
            return "正在播放DVD";
        }
    }
}

     既然抽象类不能实例化,那么这段代码为什么又可以运行呢?首先要明确上面的代码并没有实例化抽象类,只是声明了一个抽象类的对象,实例化时必须通过构造函数来实现,这里调用的是子类的构造函数,所以实例化的是子类对象,只是抽象类对象引用了子类实例。

    抽象类的派生类必须实现所有的抽象方法,必须使用override关键字,并且不能是私有的。

 

五 总结

    面向对象程式设计中的另外一个重要概念是多态性。在运行时,能通过指向基类的指针,来调用实现派生类中的方法。能把一组对象放到一个数组中,然后调用他们的方法,在这种场合下,多态性作用就体现出来了,这些对象不必是相同类型的对象。当然,如果他们都继承自某个类,你能把这些派生类,都放到一个数组中。如果这些对象都有同名方法,就能调用每个对象的同名方法。   

posted on 2010-12-10 14:39  liuling2010  阅读(360)  评论(0编辑  收藏  举报