• 也谈委托,事件和回调 cow


      今天面试问了别人问了个问题,让我举个委托的例子。我是这样说的,委托本质上就是一个函数引用,A类要想使用B类的某个方法,必须在A类中申明一个B类方法的引用才能使用,这个引用就是委托了。对方叫我说具体点,我变想边说,结果对方没有听太明白,应该是我自己思路太乱吧,在这里整理一下这个思路。

      还是从委托的概念出发,这才是委托的本质,也是最不容易忘记的。

      委托变量函数引用。这四个字够简单吧,估计看了之后想忘记挺难的,很容易推理到委托就是函数类型

      举个例子:Int变量是3的引用,那么Int是3类型。(当然int类型是值类型,这里只是做一个推理)

      对于一个具体函数,他对应的委托有应该如果定义呢?那就应该想什么特性是某类函数共有的:函数签名相同。

      至于返回值是否要求相同,暂时不知,因为一般委托都没有返回值。有机会实验一把。

      

      那么怎么使用委托呢?例如:A类有个方法C,B类需要使用方法C,那么B类需要有一个C的引用。

      伪代码如下:

      public class A

      {

        private void C(int i) {}

      }

      

      // 有了方法,才有定义委托的必要了。

      public delegate void DC(int i);  // 这一点得记住了,委托类型就是这样定义的,就是函数类型的定义。这里面delegate说明申明的是一个函数类型。

                     // 可以这样理解:delegate后面就是一个函数签名,用于描述该函数的类型,其中dc就是函数类型名,即委托名了。

      public Class B

      {

        private DC dc;  // 通过委托类型定义委托变量

      }

      现在我们需要做的事情就是将A对象的函数C复制给B对象的变量dc,因为两个变量都是私有的,所以无法做到。所以可以把委托变量暴露出来,然后在A对象中复制使用。这其中就需要A知道B,即A到B的一个单向关联的关系。当然也可以把A类中C方法暴露出来,这个时候可以直接访问C方法,就没有使用委托的必要了。

      public class A

      {

        public B _b;

        private void C(int i) {}

        public Set()

        {

          //_b.dc=c; 这显然错误,因为委托是引用类型,所以必须用new关键字来创建并赋值。

          _b.dc=new DC(C);  // 这样就将A类中函数复制给了B类中的委托变量,B类中就可以使用A类中对应的函数了。

        }

      }

      public Class B

      {

        public DC dc;  // 通过委托类型定义委托变量

      }

      下面的写出使用的代码。

      B b=new B(); //

      A a=new A();

      a._b=b;

      a.Set();

      b.dc(i); //  相当于a.C(i);

      B要调用A中的私有的C方法,B只能申明一个public类型的C方法委托变量。然后让A知道B,在A中将A的C方法复制给B对象。

      理解:(1)B无法直接访问A中的私有方法C,但可以通过申明一个C方法类型的委托变量,让委托变量访问C方法。

         (2)将C中的私有方法复制给A对象的委托变量的工作在哪里做? 在C类中做,因为如果在外面做,还是无法访问C方法。那就需要A知道B,即在A中有B的引用。

    现在再谈谈事件事件的意义大概是这样的:B象做了一个操作,A象如果订阅了这个事件,那么就可以得到通知并做相应的处理,其中这个操作就是事件。

    从定义中可以看出,B某个操作,说明正在执行B的方法,然后A的做相应的处理,说明可以触发B中的方法。总结起来,就是B以在不知道A前提下,调用B中的方法。再简洁一点,B以调用A的私有方法,这正需要委托来实现

    事件本质上也是一个委托,只是它重写“+=”运算符,实现事件的订阅(函数的赋值)。

    事件的申明:

      public Class B

      {

        public event C dc;  // 在委托签名添加event关键字,dc就是事件了

      }

       public class A

      {

        public B _b;

        private void C(int i) {}

        public Set()

        {

          //_b.dc=c; 这显然错误,因为委托是引用类型,所以必须用new关键字来创建并赋值。

          //          _b.dc=new DC(C);  // 这样就将A类中函数复制给了B类中的委托变量,B类中就可以使用A类中对应的函数了。

          _b.dc+=new DC(c); // 使用运算符+=来实现函数的复制,即事件的签约

        }

      }

      触发事件的方法还是一样的。

      B b=new B(); //

      A a=new A();

      a._b=b;

      a.Set();

      b.dc(i);

     接着谈谈回调函数。

      回调函数:一个函数传给另一个函数调用。也就是说在另一个函数中,第一个函数的委托。这个比较简单就不举例子了。

      因为回调是直接传的函数,所以跟event不同,一个event可以有多个事件对象订阅。一个回调,每次只能调用一个对象中的函数。

     

      纯属自己的理解,有问题的地方望大家指正。

  • 相关阅读:
    SessionFactory Cache 的配置
    乱码处理问题
    格式化当前日期
    JDK的安装
    内存和对象内存池技术在网游开发中的注意点和应用
    Head First设计模式C++实现Strategy模式
    介绍三种将二进制字节字符转换为ASCII方法
    C++风格的类型转换的用法
    i++循环与i循环的执行效率
    系统程序员成长计划组合的威力(一)
  • 原文地址:https://www.cnblogs.com/cowman/p/2377610.html
Copyright © 2020-2023  润新知