块和函数式编程(翻译+个人想法)
2013-07-12 13:54
253 查看
编程范式有三种:过程式编程、面向对象编程和函数式编程。大部分现代编程语言并不能单纯地归为某一范式。这些语言常常看起来属于某种范式,同时又兼具其他范式的特色。Objective-C主要是面向对象的,同时又通过块借鉴了一些函数式的特性。
函数式编程(Functional Programming,FP)
块:可以把块作为参数传递,“复制”以备稍后使用,也可以对其执行几乎所有通常会用在基本数据类型上的操作。C程序员是用函数指针做这件事的。而块区别于指针的一点是:块可以在其他方法的词法作用域中声明,而且可以在这个作用域中“捕获变量的状态”,不需要程序员做任何事块就有上下文信息。
例子:展示一个UIAlertView,当用户按下确认按钮时执行一个动作。
过程式方法:先创建一个UIAlertView对象,设置委托并实现回调,显示UIAlertView,然后释放。
- (IBAction) buttonTapped:(id) sender
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"send email"
message:@"Are you sure you want to send is now?"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"send",nil];
[alert show];
[alert release];;
}
-(void) alertView:(UIAlertView*) alertView didDismissWithButtonIndex:(NSInteger) buttonIndex
{
if(buttonIndex != [alertView cancelButtonIndex])
{
[self sendTheMail];
}
}
-(void) sendTheMail
{
//发送邮件的代码
}
现在看看一个遵循函数式范式的UIAlertView的调用
[UIAlertView showAlertViewWithTitle:@"Send email"
message:@"Are you sure you want to send it now?"
cancelButtonTitle:@"Cancel"
otherButtonTitles:[NSArray arrayWithObjects:@"send",nil]
onCompletion:^{
//发送邮件的代码
}
onCancel:^{//其他处理
}
];
函数式范式不需要实现委托,不需要分配和释放对象,不需要明确地显示警告对话框。
块是一种比较特殊的Objective-C对象。跟传统的对象不同的是,块不是在堆上创建的。主要有两个原因,一是在栈上分配空间几乎总是比在堆上快;二是出于访问其他局部变量的需要。当块作为参数传递给别的方法时,块被复制,它会从栈移动到堆上。这就意味着默认情况下块不能修改上下文数据。但是也可以修改局部变量,只是需要用__block来修饰声明变量。这个修饰符是为了命令编译器当块被复制时也把变量__block复制过去。
知道了块的原理,现在就来实现块。
(1)为UIAlertView 添加类别,头函数为UIAlertView+Blocks.h
#import <Foundation/Foundation.h>
//用typedef定义DismissBlock和CancelBlock
typedef void (^DismissBlock)(int buttonIndex);
typedef void (^CancelBlock)();
@interface UIAlertView (Blocks) <UIAlertViewDelegate>
//方法定义
+ (UIAlertView*) showAlertViewWithTitle:(NSString*) title
message:(NSString*) message
cancelButtonTitle:(NSString*) cancelButtonTitle
otherButtonTitles:(NSArray*) otherButtons
onDismiss:(DismissBlock) dismissed
onCancel:(CancelBlock) cancelled;
@end
(2)实现UIAlertView+Blocks.m
#import "UIAlertView+Blocks.h"
//为块声明静态存储空间
static DismissBlock _dismissBlock;
static CancelBlock _cancelBlock;
@implementation UIAlertView (Blocks)
//实现基于块的方法
+ (UIAlertView*) showAlertViewWithTitle:(NSString*) title
message:(NSString*) message
cancelButtonTitle:(NSString*) cancelButtonTitle
otherButtonTitles:(NSArray*) otherButtons
onDismiss:(DismissBlock) dismissed
onCancel:(CancelBlock) cancelled {
_cancelBlock = [cancelled copy];
_dismissBlock = [dismissed copy];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:[self self]
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:nil];
for(NSString *buttonTitle in otherButtons)
[alert addButtonWithTitle:buttonTitle];
[alert show];
return alert;
}
//处理UIAlertViewDelegate
+ (void)alertView:(UIAlertView*) alertView didDismissWithButtonIndex:(NSInteger) buttonIndex {
if(buttonIndex == [alertView cancelButtonIndex])
{
_cancelBlock();
}
else
{
_dismissBlock(buttonIndex - 1); // cancel button is button 0
}
}
@end
(3)调用
[UIAlertView showAlertViewWithTitle:@"Test"
message:@"Hi there"
cancelButtonTitle:@"Dismiss"
otherButtonTitles:[NSArray arrayWithObject:@"OK"]
onDismiss:^(int buttonIndex) {
NSLog(@"Button Dismissed");
}
onCancel:^ {}];
这个就跟Android中的回到函数类似了
函数式编程(Functional Programming,FP)
块:可以把块作为参数传递,“复制”以备稍后使用,也可以对其执行几乎所有通常会用在基本数据类型上的操作。C程序员是用函数指针做这件事的。而块区别于指针的一点是:块可以在其他方法的词法作用域中声明,而且可以在这个作用域中“捕获变量的状态”,不需要程序员做任何事块就有上下文信息。
例子:展示一个UIAlertView,当用户按下确认按钮时执行一个动作。
过程式方法:先创建一个UIAlertView对象,设置委托并实现回调,显示UIAlertView,然后释放。
- (IBAction) buttonTapped:(id) sender
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"send email"
message:@"Are you sure you want to send is now?"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"send",nil];
[alert show];
[alert release];;
}
-(void) alertView:(UIAlertView*) alertView didDismissWithButtonIndex:(NSInteger) buttonIndex
{
if(buttonIndex != [alertView cancelButtonIndex])
{
[self sendTheMail];
}
}
-(void) sendTheMail
{
//发送邮件的代码
}
现在看看一个遵循函数式范式的UIAlertView的调用
[UIAlertView showAlertViewWithTitle:@"Send email"
message:@"Are you sure you want to send it now?"
cancelButtonTitle:@"Cancel"
otherButtonTitles:[NSArray arrayWithObjects:@"send",nil]
onCompletion:^{
//发送邮件的代码
}
onCancel:^{//其他处理
}
];
函数式范式不需要实现委托,不需要分配和释放对象,不需要明确地显示警告对话框。
块是一种比较特殊的Objective-C对象。跟传统的对象不同的是,块不是在堆上创建的。主要有两个原因,一是在栈上分配空间几乎总是比在堆上快;二是出于访问其他局部变量的需要。当块作为参数传递给别的方法时,块被复制,它会从栈移动到堆上。这就意味着默认情况下块不能修改上下文数据。但是也可以修改局部变量,只是需要用__block来修饰声明变量。这个修饰符是为了命令编译器当块被复制时也把变量__block复制过去。
知道了块的原理,现在就来实现块。
(1)为UIAlertView 添加类别,头函数为UIAlertView+Blocks.h
#import <Foundation/Foundation.h>
//用typedef定义DismissBlock和CancelBlock
typedef void (^DismissBlock)(int buttonIndex);
typedef void (^CancelBlock)();
@interface UIAlertView (Blocks) <UIAlertViewDelegate>
//方法定义
+ (UIAlertView*) showAlertViewWithTitle:(NSString*) title
message:(NSString*) message
cancelButtonTitle:(NSString*) cancelButtonTitle
otherButtonTitles:(NSArray*) otherButtons
onDismiss:(DismissBlock) dismissed
onCancel:(CancelBlock) cancelled;
@end
(2)实现UIAlertView+Blocks.m
#import "UIAlertView+Blocks.h"
//为块声明静态存储空间
static DismissBlock _dismissBlock;
static CancelBlock _cancelBlock;
@implementation UIAlertView (Blocks)
//实现基于块的方法
+ (UIAlertView*) showAlertViewWithTitle:(NSString*) title
message:(NSString*) message
cancelButtonTitle:(NSString*) cancelButtonTitle
otherButtonTitles:(NSArray*) otherButtons
onDismiss:(DismissBlock) dismissed
onCancel:(CancelBlock) cancelled {
_cancelBlock = [cancelled copy];
_dismissBlock = [dismissed copy];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:[self self]
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:nil];
for(NSString *buttonTitle in otherButtons)
[alert addButtonWithTitle:buttonTitle];
[alert show];
return alert;
}
//处理UIAlertViewDelegate
+ (void)alertView:(UIAlertView*) alertView didDismissWithButtonIndex:(NSInteger) buttonIndex {
if(buttonIndex == [alertView cancelButtonIndex])
{
_cancelBlock();
}
else
{
_dismissBlock(buttonIndex - 1); // cancel button is button 0
}
}
@end
(3)调用
[UIAlertView showAlertViewWithTitle:@"Test"
message:@"Hi there"
cancelButtonTitle:@"Dismiss"
otherButtonTitles:[NSArray arrayWithObject:@"OK"]
onDismiss:^(int buttonIndex) {
NSLog(@"Button Dismissed");
}
onCancel:^ {}];
这个就跟Android中的回到函数类似了
相关文章推荐
- 持续更新 iText in Action 2nd Edition中文版 个人翻译
- 【MCM-2017】2017年数学建模美赛题目原文及翻译-A (个人思路)
- 关于字符串匹配Sunday算法的个人想法
- 以前也有过楼主这个阶段,工作两年感觉前端不过如此,不过后来还是逐渐突破了。尤其是使用了angularJS后。 现在转去做C++开发,对比后发现前端实在是太简单了,别喷我,个人想法,当初也是觉得JS水
- [个人翻译]GitHub指导文件(GitHub Guides[Hello World])
- [个人翻译]GitHub指导文件(GitHub Guides[Hello World])
- 《ScholarlyMarkdown Syntax Guide》中文翻译+个人使用笔记
- 《Django By Example》第七章 中文 翻译 (个人学习,渣翻)
- Fixing Pathfinding Once and For All (个人翻译)
- 还在吐槽翻译的外版书质量差吗?谈谈我个人的理解
- 生活随笔:纯粹个人想法
- Spice Agent Protocol (对官网文档的翻译及一些个人理解)
- WSO2 Web Services Framework for C++--根据官方文档翻译的,确实翻译的简陋,只是抱着可能对某些同学有帮助的想法发布出来的,也为了后续的文章做准备
- 关于google.cn关闭的一点儿个人想法
- 2016年数学建模美赛题目原文及翻译-A [个人思路]
- [原创]个人对伊拉克进入亚洲杯决赛之后国内频繁的自杀爆炸一点小想法
- 链表空指针建立(个人想法)
- 持续更新 iText in Action 2nd Edition中文版 个人翻译
- 函数式编程(F#)个人随感
- [个人]加入了ruby hacking guide的中文翻译团队