C#多态的总结

什么是多态
专业述语:不同的对象对同一消息作出不同的响应就是多态。
生活例子:老板对员工说“员工们开始工作”,程序员听到后写代码,销售人员听到后出去跑业务,客服人员听到后给客户打电话做回访。
不可能让老板说“程序员你们快写代码,销售人员你们快去跑业务,客服人员你们快去电话回访”。如果公司发展壮大,又增加了一个员工类型“公关人员”,则老板又要加句“公关人员快去宣传”,将来不断增加员工类型的话,那老板岂不累晕啊,或者老板出差很久回来时并不知道增加新的员工类型或去掉了员工类型,那他说的话会出错啊。这样就导致了不灵活(因为每次都要修改所说的),增加了依赖(因为每次都要清楚知道有哪些员工类型)。
从这个生活的例子可以看出,有两种类型:老板、员工。员工又分为程序员、销售员、客服员等等子类型。还有一种行为:工作。
下面把生活中的例子用代码来实现。

一、基于共同基类的多态

// 员工类
    public abstract class Employee
    {
        //姓名
        public string Name { get; set; }

        //工作
        public abstract void Work();
}
//程序员类
    public class Programmer : Employee
    {
        public override void Work()
        {
            Console.WriteLine(Name + "程序员开始写代码");
        }
 }
//销售员类
    public class Seller : Employee
    {
        public override void Work()
        {
            Console.WriteLine(Name + "销售员开始出去跑业务");
        }
 }
//客服类
    public class Srv : Employee
    {
        public override void Work()
        {
            Console.WriteLine(Name + "客服开始打电话回访");
        }
}
// 老板类
    public class Boss
    {
        //老板向员工们发话
        public void SendCommand(List<Employee> employeeList)
        {
            foreach (var emp in employeeList)//员工们开始工作吧
                emp.Work();
        }
}
static void Main(string[] args)
        {
            Employee employee1 = new Programmer() { Name = "程大大" };
            Employee employee2 = new Seller() { Name = "销美美" };
            Employee employee3 = new Srv() { Name = "客小服" };

            List<Employee> employeeList = new List<Employee>();
            employeeList.Add(employee1);
            employeeList.Add(employee2);
            employeeList.Add(employee3);

            Boss boss = new Boss();
            boss.SendCommand(employeeList);
            Console.ReadLine();
        }

当增加新的员工类型“公关人员”时,现有的员工种类和老板类都不需要修改,只需新增就行了。就这遵循了面向对象的“开闭原则”(对功能扩展是开放的,对修改则是封闭的)。老板只依赖于Empolyee这个类,极大降低了依赖。
当然这个例子也可不用抽象类加抽象方法,用正常类加virtual方法也行。
不过使用正常类不太适合,当实例化一个员工Employee对象时,我们并不清楚是哪种员工,概念太模糊,所以用抽象的才最合适。
二、基于共同接口的多态

// 员工接口
    public interface IEmployee
    {
        //姓名
        string Name { get; set; }//属性的本质是方法,所以可在接口中定义

        //工作
        void Work();
}

//程序员类
    public class Programmer : IEmployee
    {
        public string Name { get; set; }

        public void Work()
        {
            Console.WriteLine(Name + "程序员开始写代码");
        }
}

//销售员类
    public class Seller : IEmployee
    {
        public string Name { get; set; }

        public void Work()
        {
            Console.WriteLine(Name + "销售员开始去出跑业务");
        }
}

//客服类
    public class Srv : IEmployee
    {
        public string Name { get; set; }

        public void Work()
        {
            Console.WriteLine(Name + "客服开始打电话回访");
        }
}
// 老板类
    public class Boss
    {
        //老板向员工们发话
        public void SendCommand(List<IEmployee> employeeList)
        {
            foreach (var emp in employeeList)//员工们开始工作吧
                emp.Work();
        }
}
static void Main(string[] args)
        {
            IEmployee employee1 = new Programmer() { Name = "程大大" };
            IEmployee employee2 = new Seller() { Name = "销美美" };
            IEmployee employee3 = new Srv() { Name = "客小服" };

            List<IEmployee> employeeList = new List<IEmployee>();
            employeeList.Add(employee1);
            employeeList.Add(employee2);
            employeeList.Add(employee3);

            Boss boss = new Boss();
            boss.SendCommand(employeeList);
            Console.ReadLine();
        }

接口的本质的是抽象类,所以和(一)中的一样。当然这个例子使用接口不合适,因为属性在各个子类都要实现一下。

三、基于共同委托的多态

//程序员类
    public class Programmer
    {
        public string Name { get; set; }

        public void WriteCode()//写代码
        {
            Console.WriteLine(Name + "程序员开始写代码");
        }
    }
//销售员类
    public class Seller
    {
        public string Name { get; set; }

        public void TakeBusiness()//跑业务
        {
            Console.WriteLine(Name + "销售员开始去出跑业务");
        }
}
//客服类
    public class Srv
    {
        public string Name { get; set; }

        public void CallPhone()//打电话
        {
            Console.WriteLine(Name + "客服开始打电话回访");
        }
}
// 老板类
    public class Boss
    {
        //老板说开始工作
        public void SendCommand(List<Action> actionList)
        {
            foreach(var action in actionList)
                action?.Invoke();
        }
}
static void Main(string[] args)
        {
            var employee1 = new Programmer() { Name = "程大大" };
            var employee2 = new Seller() { Name = "销美美" };
            var employee3 = new Srv() { Name = "客小服" };

            Action action1 = employee1.WriteCode;
            Action action2 = employee2.TakeBusiness;
            Action action3 = employee3.CallPhone;

            List<Action> actionList = new List<Action>();
            actionList.Add(action1);
            actionList.Add(action2);
            actionList.Add(action3);

            Boss boss = new Boss();
            boss.SendCommand(actionList);

            Console.ReadLine();
        }

当然这里使用委托是不合适的,只是为了演示多态的另一种形式。委托的本质也是一个类,即action1,2,3都会被编译成类。个人认为也满足述语:不同的对象对同一消息作出不同的响应就是多态这句话。

猜你喜欢

转载自blog.csdn.net/junshangshui/article/details/78956882
今日推荐