第13节:事件、委托(抱歉,更新来迟了,昨天忙项目忙了一天,所以停更了一天,今天继续。)
今天讲述事件,一般讲述事件必定跟着委托,接下来先简单了解下什么是事件吧。
一、事件
事件:声明一个事件,其实本质类似声明了一个及逆行了封装的委托变量。使用事件不仅能获取比委托更好的封装能力还能限制含有事件能力的权限。
本质:事件应该由事件的发布者触发,而不应该由事件的客户端自己来触发
事件的使用步骤:
1)声明委托类型
2)创建委托
3)创造接受者
4)绑定事件
5)通知接受者,执行方法
注意:发送(或者引发)事件的类叫做发行者,接收或处理事件的类叫做订阅者,事件的触发必须在发行者内部
下面通过四个例子来展示事件的使用
例1:
namespace Shijian
{
//定义一个类,作为事件的发行者
public class GreetingManager
{
//声明一个委托
public delegate void Greeting(string name);
//声明一个事件,类型就是定义的类型委托
public event Greeting makeGreet;
//事件发行者方法
public void GreetPeople(string name,int num,string str)
{
//触发事件
makeGreet(name);
}
}
public class Program
{
public static void Taiguo(string name)
{
Debug.Log ("萨瓦迪卡"+name);
}
public static void Japan(string name)
{
Debug.Log ("摩西摩西"+name);
}
public static void China(string name)
{
Debug.Log ("中国"+name);
}
}
class MainClass
{
public static void Main (string[] args)
{
//创建一个事件的发行者对象
GreetingManager greetManager = new GreetingManager ();
//绑定事件
greetManager.makeGreet += Program.Taiguo;
greetManager.makeGreet += Program.Japan;
greetManager.makeGreet += Program.China;
//发行者触发事件,通过接受者执行方法
greetManager.GreetPeople("美女",123,"hello");
}|
}
}
例2:
using System;
/*发微博的练习:
* 1、创建一个类作为微博的发布者(博主),类中有一个发微博
* 的委托,在类中声明发微博的事件,添加发微博的方法,
* 在方法中去判断如果有人注册了这个事件,就去通知注册
* 的人
* 2、创建粉丝类,给博主添加粉丝
*/
namespace Shijian
{
public class WeiBo
{
public WeiBo ()
{
}
//声明一个发微博的委托
public delegate void PublicBlogDelegate();
//声明发微博的事件
public event PublicBlogDelegate outPutEvent;
//添加发微博的方法
public void PublicBlog ()
{
//开始发微博,之前都是发微博的准备
Debug.Log ("博主:\n突然好想做一首诗啊\n");
//如果有人关注了博主,就去通知这些粉丝
if (outPutEvent != null) {
//通知粉丝(订阅者)
outPutEvent ();
}
}
}
public class User1
{
public static void Comment1(){
Debug.Log ("一楼");
}
}
}
例3:
using System;
namespace Shijian
{
public class RSH
{
public RSH ()
{
}
public delegate void Rsh(double temp); //声明一个热水壶委托
public event Rsh Sw; //声明热水壶事件 报警 水温
public void Shui(double a){ //添加热水壶报警方法
for (double i = 0; i < 100; i+=0.2f) {
if (i >= a) {
//说明水温达到了报警值,这时候需要观察者来做出反应了
Sw (i);
} else {
Debbug.Log ("加热中....");
}
}
}
}
public class Ysq{
public static void Comment1(double a){
Debbug.Log ("警告!");
}
}
public class Xsp{
public static void Comment2(double a){
Debbug.Log ("当前水温为:{0}",a);
}
}
}
例4:
using System;
namespace Shijian
{
public class Ju
{
public Ju()
{
}
public delegate void Jiangjun(); //定义一个将军委托
public event Jiangjun Shaibei; //发生的事件 摔杯子
public void Shai(){ //方法
Debug.Log ("将军摔杯子");
if (Shaibei!=null) {
Shaibei ();
}
}
}
public class sr //士兵杀人
{
public sr(Jujiangjun)
{
//让士兵监听将军摔杯子事件
jiangjun.Shaibei+=this.kill;
}
public void kill(){
Debug.Log ("士兵杀人");
}
}
}
二、委托
1.委托
委托是一个类型安全的对象,委托是一个可以引用方法的对象,当创建一个委托,也就是创建了一个引用方法对象,通过这个对象可以调用它指向方法。
委托在使用之前要声明一个类型,使用delegate
委托使用步骤:
1)声明委托类型(数据类型)格式:访问修饰符 delegate 返回值类型 委托
2)创建委托对象(变量、实例)
格式:委托名 委托实例名=new 委托名(某个方法名/也可不写);
3)将创建的委托对象和引用的方法关联起来委托实例名=某个方法名
4)使用委托对象调用对应的方法 委托实例名(实参);
委托使用注意事项:
1)委托和方法必须具有相同的参数和返回值
2)委托可以调用多个方法,即一个委托对象可以维护一个可调用方法的列表,而不仅是单个的一个方法,称为多播委托
3)使用+=,-=运算否来给委托对象添加可调用的方法
2.委托的其他四种形式
1、匿名委托-相当于是绑定了没有方法名的方法
格式:委托名 变量名 =delegate(参数类型1 参数名……){ 语句; };
参数:相当于绑定方法的形参
{ }中的语句:相当于绑定方法的方法体
由于是赋值的过程、本质上十个语句,所以最后大括号后有分号
2、lamda表达式类型委托
格式:(参数)=> { 语句; }
参数:相当于绑定方法的参数
=>是lamda表达式的一个操作符,左边定义一个参数列表,右边对应操作
{ }里面的语句相当于绑定方法的方法体
注意:不要忘了最后的分号
下面通过几种案例来展示了委托的实现方式
例1:
//使用匿名委托,求出1-100之间的被15整除的书,打印
SumDelegate sumDele = (int num1, int num2) => {
Debug.Log("两个数的和为:{0}", num1 + num2);
};
sumDele (3, 7);
//使用lamda表达式委托,实现两个整数的交换
NumDelegate unmDele = (int a, int b) => {
int temp;
temp = a;
a = b;
b = temp;
Debug.Log ("交换后的:{0} {1}", a, b);
};
unmDele (1, 2);
例2:
/*Func委托
* 格式:
* Func<int,int,int>func=delegate(int a,int b){
* return a*b;
* };
* 使用Func泛型,前面两个是参数类型,后面是一个返回值类型
* Func委托赋值时既可以绑定匿名委托也可以绑定Lamda委托这种委托一定有返回值
*/
Func<int,int,int> func = delegate (int a, int b) {
return a * b;
};
Debug.Log (func (2, 3));
Func<int> func1 = delegate {
Debug.Log ("不带参数");
return 3;
};
func1 ();
//练习:使用Func委托实现返回三个数中的最大值,使用Lamda表达式来实现
Func<int,int,int,int> maxDele = (int a, int b, int c) => {
return (a > b ? a : b) > c ? (a > b ? a : b) : c;
};
Debug.Log ("最大值为:" + maxDele (4, 2, 9));
例3:
/*Action委托
* 格式:
* Action<参数类型1,参数类型2……参数类型n>委托变量名=delegate(参数类型1,参数类型2……参数类型n)
* {
* 语句;
* };
* 使用Action委托,< >里放的是参数类型,这种类型的委托可以复制
* 匿名委托,Lamda委托和方法
* 注意 这种委托不能有返回值
*
*/
Action<string> action = (string str) => {
Debug.Log ("我床塌了" + str);
};
action ("今晚去你那睡");
//使用Action委托实现将一个数变为之前的2倍
Action<int> numDelegate = delegate(int a) {
a *= 2;
Debug.Log (a);
};
int number = 5;
numDelegate (number);
Debug.Log (number);