文档章节

[iOS、Unity、Android] 浅谈闭包的使用方法

浩浩老师
 浩浩老师
发布于 2015/09/07 15:49
字数 1712
阅读 50
收藏 0

前言


我们经常所编程语言的的进步速度是落后于硬件的发展速度的。

但是最近几年,闭包语法在各个语言中都有自己的体现形式,例如

  •  C语言中使用函数指针作为回调函数的入口;

  •  Java和C#语言中的Lambda语法表达式;

  •  Objective-C语言中的Blocks语法;

  •  C#语言中的Delegates语法;

  •  C++语言中的Functions对象;

历史


Peter J. Landin 在1964年将术语 闭包 定义为一种包含 环境成分 和 控制成分 的实体,用于在他的SECD 机器上对表达式求值。Joel Moses 认为是 Landin 发明了 闭包 这一术语,用来指代某些其开放绑定(自由变量)已经由其语法环境完成闭合(或者绑定)的 lambda 表达式,从而形成了 闭合的表达式,或称闭包。

 

使用方法


C++语言中的Functions对象:

C++11标准开始支持闭包,这是一种特殊的函数对象,由特殊的语言结构—— lambda表达式 自动构建。

C++闭包中保存了全部nonlocal变量的拷贝或引用。

如果是对外界环境中的对象的引用,且闭包执行时该外界环境的变量已经不存在(如在调用栈上已经unwinding),那么可导致undefined behavior,因为C++并不扩展这些被引用的外界环境的变量的生命期。

常见代码如下:

//
//  main.cpp
//  Interface
//
//  Created by lewis on 4/30/15.
//  Copyright (c) 2015 lewis. All rights reserved.
//

#include <iostream>
#include <string>
#include <vector>

using namespace std;

//构造string向量
vector<string> GetNameList()
{
    static vector<string> names;
    
    names.push_back("刘辉");
    names.push_back("李静波");
    names.push_back("崔亚允");
    names.push_back("赵雅");
    names.push_back("管辉");
    names.push_back("白志刚");
    names.push_back("王斌");
    names.push_back("白雅静");
    names.push_back("张浩");

    return names;
}

void foo(string myname) {
    vector<string> names = GetNameList();
    
    //通过遍历string向量,使用闭包完成判断条件
    vector<string>::iterator i = find_if(names.begin(), names.end(), [&](const string& s){
        
        //判断操作值与参数相等是否相等
        return s == myname;
    });
    

    
    //输出判断得到的结果
    cout  <<(string)(*i) << endl;
}

int main(int argc, const char * argv[]) {

    foo("刘辉");
    
    return 0;
}

1、声明闭包变量

C++中闭包的声明语法,要使用 function 类型来声明变量,如下所示

 std::function<float(float)> colsure; 

其中,第一个 float 代表了闭包的返回值类型,第二个 float 代表了闭包的参数数据类型为浮点型

2、赋值闭包变量

C++中闭包的赋值语法,要使用 [=] 或 [&] 符号开头,如下所示

colsure = [=](float f) {
      f += 10.0f;      return f;
};

 

其中, [=] 代表了我们将要进行的闭包传值是单向赋值

 [&] 在使用过程中,经常作为引用传值使用,如下所示

std:function<float(float&)> col;
col = [&](float& f){
      f += 10.0f;      return f;      
};

 3、使用闭包变量

使用 [=] 和 [&] 声明并且赋值后的闭包变量,在使用结束后的结果如下

//声明一个浮点型变量float floatValue = 1.0f;//声明计算结果浮点型变量float resultValue = 0.0f;//使用[=]类型的闭包变量resultValue = colsure(floatValue);//输入结果std::cout<<floatValue<<":"<<resultValue<<endl;//使用[&]类型的闭包变量resultValue = col(floatValue);
std::cout<<floatValue<<":"<<resultValue<<endl;

通过打印的结果,

1.0:10.0
10.0:10.0

 

 [=] 和 [&] 分别代表了值传递和引用传递的两种方式。

 

Objective-C中的Blocks变量:

Blocks语法支持的系统版本为OS X 8或者更高版本,iOS 4或者更高版本.

常见的代码如下:

//
//  main.m
//  BlockSample
//
//  Created by lewis on 4/30/15.
//  Copyright (c) 2015 lewis. All rights reserved.
//

#import <Foundation/Foundation.h>


NSArray *GetNameList()
{
    static NSMutableArray *names = nil;
    
    if (names == nil) {
        names = [[NSMutableArray alloc] init];
        [names addObject:@"刘辉"];
        [names addObject:@"崔亚允"];
        [names addObject:@"李静波"];
        [names addObject:@"赵雅"];
        [names addObject:@"管辉"];
        [names addObject:@"王斌"];
        [names addObject:@"张浩"];
    }
    
    return names;
}

void foo(NSString *myname)
{
    //获取到姓名列表
    NSArray *names = GetNameList();
    
    
    //通过遍历数组对象,使用Block进行判断
    NSInteger index = [names indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        return [obj isEqualToString:myname];
    }];
    
    
    //输出结果
    NSLog(@"%@",names[index]);
}


int main(int argc, const char * argv[])
{
    foo(@"崔亚允");
    return 0;
}

1、声明Block语法变量

 float(^block)(float); 

我们会发现,Blocks语法变量的声明语法与函数指针变量的声明语法 float(*pointer)(float); 非常类似,只是在运算符号上有区别;

2、赋值Block语法变量

block = ^ (float f){
        f += 10.0f;        return f;
};

 在对Blocks变量进行赋值时,要注意所有的Block变量都是用 "^" 运算符号来开头,并且有返回值类型的Block变量,在Block代码块内部的return 返回类型要相同。

 

C#语言中的Lambda表达式:

Lambda表达式实在C#4中出现的语法糖,用来提高程序的开发效率,简化Func类型变量和delegate对象的写法。

常见的代码如下:

using System;
using System.Collections.Generic;

namespace LambdaSample
{
	class MainClass
	{
		public static List<string> GetNameList()
		{
			List<string> names = new List<string> ();

			names.Add ("刘辉");
			names.Add ("崔亚允");
			names.Add ("李静波");
			names.Add ("赵雅");
			names.Add ("管辉");
			names.Add ("白志刚");

			return names;
		}

		public static void foo(string myname)
		{
			//获取姓名列表
			List<string> names = GetNameList ();

			//通过Lambda表达式作为判断条件进行查询
			string result = names.Find ((x) => {
				return x == myname;
			});

			//输入查询结果
			Console.WriteLine(result);
		}

		public static void Main (string[] args)
		{
			//测试
			foo ("崔亚允");
		}
	}
}

1、声明C#语言中的Lambda表达式变量

在C#语言中,可以通过 Func 类型来声明Lambda变量,如下所示:

Func<float,float> func;

或者使用 delegate 类型来声明Lambda变量,如下所示:

//定义一个delegate类型Interfacedelegate float Interface(float x);public static void Main (string[] args)
{     //使用Interface类型来声明Lambda变量     Inteface inter_func;    
}

 

2、赋值C#语言中的Lambda表达式变量

在C#语言中,使用 => goes to 运算符来生成变量,如下所示:

func = (x) => {
    x += 10.0f;    return x;
};

  => goes to运算符的左边是闭包类型的浮点型参数,右边是闭包变量准备进行的逻辑运算,以 {} 包括。

3、使用C#语言中的Lambda表达式变量

和调用函数一样,如下所示:

//声明Func类型变量Func<float,float> func;//为func赋值Lambda闭包func = (x) => {
    x += 10.0f;    return x;
};float floatValue = 1.0f;float resultValue = 0.0f;//调用func变量,计算结果并且赋值给resultValueresultValue = func (floatValue);//进行输出Console.WriteLine (resultValue);

 

 

总结 


其实在计算机科学中,闭包Closure)是词法闭包Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

需要注意的一点是

闭包一词经常和匿名函数混淆。这可能是因为两者经常同时使用,但是它们是不同的概念!!!!

本文转载自:http://www.cnblogs.com/daxiaxiaohao/p/4468534.html

浩浩老师
粉丝 1
博文 80
码字总数 0
作品 0
海淀
程序员
私信 提问
Unity与IOS交互,调用IOS系统相机和相册

前面两篇总结了一下unity与android的简单交互和调用安卓系统相机和相册,比较蛋疼的是,后来发现不同的测试机上会有不同的bug。。。下阶段要一个一个的解决一下 今天总结一下与IOS的交互。这...

qq_32587659
2018/05/16
0
0
Unity免费插件分享 Bluetooth LE for iOS, tvOS and Android 2.3.0 Unity蓝牙插件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/KiTok/article/details/83177703 Unity免费插件分享 Bluetooth LE for iOS, tvOS and Android 2.3.0 Unity蓝牙...

KitStar
2018/10/19
0
0
Unity3D调用快三平台出租原生Android和IOS复制粘贴功能

今天要实现快三平台出租 haozbbs.com Q1446595067 用Unity调用设备的复制到粘贴板功能,Unity没有实现这个功能,所以需要调用设备原生的功能了,在网上找了一下,不算太多而且大多都不能使用...

yuus
2018/07/10
0
0
Unity 游戏引擎的移动基本版从今天起免费提供

著名游戏引擎Unity的移动基本版从今天起免费,这意味着 iOS, Android 和 BlackBerry 10 的开发者门槛进一步降低。在今年的 Unite 2013 大会上,Unity CEO David Helgason 宣布,原本需要分别...

oschina
2013/05/22
7.7K
41
Unity开发者制作iOS、安卓手机游戏的常用Unity插件推荐合集

越来越多的移动游戏开发者选择使用Unity进行开发,Unity还可以开发跨平台APP。本文推荐了一些用Unity开发手机游戏时的一些常用插件,希望可以帮助到各位开发者。 1:Ultimate Mobile Pro 包含...

Unity老司机
08/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JS--function

一、声明提前(hoist) 在js程序开始执行前,引擎会查找所有var声明的变量和function声明的函数,集中到当前作用域顶部集中创建,赋值留在原地 二、三种创建函数的方式 1、声明方式创建函数-...

wytao1995
今天
4
0
微服务之间调用控制器注解类型的差异

今天在一个业务服务通过Feign调用文件服务上传文件时遇到了几个问题: 1. 提示http请求头过大的问题; 此时需要修改bootstrap.yml,加入 server: max-http-header-size: 10000000 用以放大...

不再熬夜
今天
6
0
用 4G 工作是什么体验

七月开始,因为工作原因,在公司附近租了个住处,方便工作。离公司近了,感觉就是不一样,之前每天 5:30 就要起床赶地铁,现在可以睡到自然醒,一看才 7 点,悠闲的起床洗漱,踱步到公司,都...

zzxworld
今天
6
0
sonar报错volatile

问题发生 原先代码如下: //认证授权码private static volatile String AUTHORIZATION_CODE = "init"; git push 之后,sonar认为这是个bug检测报告截图如下: 分析排查 解释说明: Markin...

开源小菜鸟2333
今天
5
0
《Java实践指南》--读后

闲读《Java实践指南》... 1.lvy 某些项目中能够看到ivy.xml。早期使用ant的项目中,常常用ivy.xml来下载项目依赖。 2.ant 作为java程序员,应该都知道ant,虽然可能用过的人不多。为什么ant...

RippleChan
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部