• 协变和逆变


    协变:派生类=>基类

    假设有这样一个类:

        class Person : ICloneable
        {
            public object Clone()
            {
                Console.WriteLine("this is Clone");
                return new Person();
            }
        }

    但是由于我们知道是返回一个Person类的实例,所以返回类型 object 写在这里总会觉得很别扭,我们希望写成: 

        class Person : ICloneable
        {
            public Person Clone()
            {
                Console.WriteLine("this is Clone");
                return new Person();
            }
        }

    显然,这是错的!虽然这是错的,但这就是返回类型的协变性,只是非泛型接口和方法重载不支持这一特性.

    如果一定要这样写,只能使用显示接口实现:

        class Person : ICloneable
        {
            object ICloneable.Clone()
            {
                Console.WriteLine("this is ICloneable.Clone");
                return Clone();
            }
    
            public Person Clone()
            {
                Console.WriteLine("this is Clone");
                return new Person();
            }
        }

    如果定义的是 ICloneable类型, 则调用上面的方法;

    如果定义的是 Person 类型,则调用下面的方法;

                ICloneable ic = new Person();
                ic.Clone();
                Person p = new Person();
                p.Clone();

    逆变:基类=>派生类

    假设我们有这样一个类:

        class Person
        {
            public virtual void Process(Person person)
            {
                Console.WriteLine("this param is person");
            }
        }

    我们想在派生类中写如下一个方法:

        class Student : Person
        {
            public override void Process(object o)
            {
                Console.WriteLine("this param is obj");
            }
        }

    看起来很合理, 因为 object 是基类,肯定可以接受 Person 类的实例呀,这称为参数类型的逆变性

    但实际上,和协变一样,非泛型接口接口和方法不支持

    委托返回类型的协变性:

    一个返回值为 基类 的委托变量,可以接收一个返回值为 派生类 的委托实例

        class Program
        {
    
            public delegate Parent DelgParent();
            public delegate Child DelgChild();
    
            static void Main(string[] args)
            {
                DelgParent del1 = Method1;
                DelgChild del2 = Method2;
    
                del1 = Method2;
                //del2 = Method1;//异常,返回类型错误
    
                Console.ReadKey();
            }
    
            public static Parent Method1() { return null; }
    
            public static Child Method2() { return null; }
        }
    
        class Parent { }
    
        class Child : Parent { }

    委托参数的逆变性:

    一个参数为 派生类 的委托变量, 可以接收一个参数为 基类 的委托实例

        class Program
        {
            delegate void PersonDelegate(Student s);
            static void Main(string[] args)
            {
                PersonDelegate pd = Test;
                pd(new Student());
    
                Console.ReadKey();
            }
    
            static void Test(Person p)
            {
                Console.WriteLine("person");
            }
        }
  • 相关阅读:
    【设计模式】策略模式
    【设计模式】模板方法模式
    【C++】《Effective C++》第五章
    【C++】《Effective C++》第四章
    free命令详解(内存)
    top命令详解(动态进程)
    ps命令详解(静态进程)
    SpringBoot_集成Redis
    SpringBoot_热部署插件
    SpringBoot_实现RESTfull API
  • 原文地址:https://www.cnblogs.com/refuge/p/8584894.html
Copyright © 2020-2023  润新知