在正常的开发中我们用到的第三方框架就有一个很好的体现了函数式编程和链式编程----Masonry。
例如:
Masonry 经典的代表
[v mas_makeConstraints:^(MASConstraintMaker *make) {
// 1. 函数式编程:
// equalTo(self.view)
// offset(40)
// 2. 链式编程
// equalTo(self.view).offset(40)
make.top.equalTo(self.view).offset(40);
make.size.mas_offset(CGSizeMake(100, 100));
make.centerX.equalTo(self.view).offset(-40);
}];
现在我们自己尝试来做函数式编程,新建一个Person类,在Person头文件声明并实现两个方法:
@interface Person : NSObject
- (void)run;
- (void)eat;
@end
#import "Person.h"
@implementation Person
- (void)run {
NSLog(@"%s", __FUNCTION__);
}
- (void)eat {
NSLog(@"%s", __FUNCTION__);
}
@end
在ViewController中调用Person中的两个方法:
Person *person = [Person new];
// 1> run 和 eat 需要单独调用!
// 2> 不能随意组合顺序!
[person run];
[person eat];
这是传统的写法,run和eat只能单独去调用,并不能去组合调用,现在我们来定一个目标1:链式编程
// 目标1:链式编程
// 这是我们想要实现的目标,方法可以自由组合
[[person run] eat ];
[[person eat] run ];
// 解决办法:在[person run] 方法后返回一个person对象,用person对象去调用person内的方法,即:
// 实现如下效果
id obj = [person run1];
[obj eat1];
obj其实就是一个person对象,用person对象调用person内的方法必然没有问题,有了这个目标之后我们现在开始改造代码:
@interface Person : NSObject
- (void)run;
- (void)eat;
- (Person *)run1;
- (Person *)eat1;
@end
@implementation Person
- (Person *)run1 {
NSLog(@"%s", __FUNCTION__);
return self;
}
- (Person *)eat1 {
NSLog(@"%s", __FUNCTION__);
return self;
}
在person类内新增加run1方法和eat1方法
id obj = [person run1];
[obj eat1];
id obj2 = [person eat1];
[obj2 run1];
NSLog(@"---");
[[person run1] eat1];
以上代码输出为:
可以看到我们实现了我们的目标1:链式编程,但是还没有实现函数式编程,现在我们定义目标2:函数式编程
// 目标2:函数式编程
// 函数式编程的特点是用 '()'去调用方法,那么在OC中我们在什么时候回用到 '()'调用方法呢
// 相信很多人第一个想到的应该就是Block
/**
person.run2().eat2();
person.eat2().run2();
以上两行代码是我们现在需要实现的目标
*/
接着到Person类内改造代码:
@interface Person : NSObject
- (void)run;
- (void)eat;
- (Person *)run1;
- (Person *)eat1;
// 关于链式编程和函数式编程
// 如果要实现函数式编程,需要返回 `block`
- (Person * (^)())run2;
- (Person * (^)())eat2;
@end
@implementation Person
- (Person * (^)())run2 {
Person * (^runBlock)() = ^ {
NSLog(@"run2");
return self;
};
return runBlock;
}
- (Person *(^)())eat2 {
return ^ {
NSLog(@"eat2");
return self;
};
}
@end
在ViewController内实现方法调用:
// 目标2: 函数式编程!
// person.run2().eat2();
// person.eat2().run2();
// 需求 :person.run2() => person.eat2();
person.run2().run2().eat2().run2();
输出如下:
我们看到现在已经实现了函数式编程。但是还有一个问题,在Masonry中()执行方法时是带有参数的,我们继续来改造代码:
// 在block中是可以带参数的,所以现在对代码进行如下改动
@interface Person : NSObject
- (void)run;
- (void)eat;
- (Person *)run1;
- (Person *)eat1;
// 关于链式编程和函数式编程
// 如果要实现函数式编程,需要返回 `block`
- (Person * (^)())run2;
- (Person * (^)())eat2;
// 返回的 block 可以接参数
- (Person * (^)(NSString *food))eat3;
- (Person * (^)(double distance))run3;
@end
@implementation Person
- (Person *(^)(NSString *))eat3 {
return ^ (NSString *food) {
NSLog(@"吃 %@", food);
return self;
};
}
- (Person *(^)(double))run3 {
return ^ (double distance) {
NSLog(@"跑 %f", distance);
return self;
};
}
@end
继续回到ViewController内调用方法:
// 目标2: 函数式编程!
// person.run2().eat2();
// person.eat2().run2();
// 需求 :person.run2() => person.eat2();
person.run2().run2().eat2().run2();
NSLog(@"---");
person.run3(1000).eat3(@"water").run3(1000).eat3(@"water");
现在看输出:
到目前为止我们已经实现了链式编程和函数式编程。感谢刀哥,有刀哥的分享才有的这篇文章。