今天面试问了别人问了个问题,让我举个委托的例子。我是这样说的,委托本质上就是一个函数引用,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可以有多个事件对象订阅。一个回调,每次只能调用一个对象中的函数。
纯属自己的理解,有问题的地方望大家指正。