最近看到了链式编程和函数式编程这两个概念,这两天不是那么的忙 所以也研究了下这两个概念;
在查询链式编程和函数式编程的概念时突然想到了链式编程和函数式编程最典型的代表是Masonry 比较完美的实现了函数式编程和链式编程 例如
[viewOne mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view).offset(100);
make.centerX.equalTo(self.view.mas_centerX).offset(100);
make.height.mas_equalTo(100);
make.width.mas_equalTo(100);
}];
其实 仔细考虑了下 所谓的链式编程其实就是 在返回值的基础上 继续调用方法,那么问题来了 什么样的返回值才能调用方法 答案是 对象 只要返回对象 然后调用对应的对象方法即可实现 链式编程 例如 最简单的链式编程
- (Person *(^)())eat3;
- (Person *(^)())run3;
[[person eat] run];
这样的链式编程 和Masonry 确实有点相差甚远
我们知道在OC中的方法调用是 发送消息的方式实现的那么 要实现 person.eat 该怎么实现呢?
那么我们就想到了 Xcode的编译器特性 类似于 getter 和setter方法,尤其是getter方法 就是将 NSString *nameOne = peron.name 转化成了 NSString *nameOne = [peron name] 那么类似的做法 我们是不是可以将 方法调用写成 : person.eat呢?答案是可以的 但是这样是有警告的但是 可以运行 那么只要我的eat 方法的返回值是Person 类对象 那么我就可以实现链式编程 ,但是这样写又没有什么意义,我们观察Maronry中是将函数式编程和链式编程结合起来使用的那么我们先了解下OC中的函数式编程的实现
先介绍下 函数式编程 然后慢慢过渡到链式编程
首先所谓函数式编程 就是通过类似于 函数调用的方式实现想要的功能即 method(); 这样的方式,
那么我们知道在OC能用method() 这样调用,只有一个可以实现,那就是BLOCK, 我们在调用BLOCK时 不就是这样调用的吗? 那么我们知道只要我的一个方法的返回值是BLOCK的时候就可以使用函数式调用了例如
- (void(^)())eat2;
- (void(^)())run2;
- (void (^)())eat2 {
return ^{
NSLog(@"block === %s",__func__);
};
}
- (void (^)())run2 {
return ^(){
NSLog(@"block == %s",__func__);
};
}
但是这样具有局限性就是只能调用一次
person.eat2();
person.run2();
不能实现 person.eat2().run2();
那么我们猜想了只要eat2中block的返回值是Person类对象 是不是就可以实现了呢?
于是 测试例子
- (Person *(^)())eat3;
- (Person *(^)())run3 ;
- (Person *(^)())eat3 {
return ^(){
NSLog(@"block == %s",__func__);
returnself;
};
}
- (Person *(^)())run3 {
return ^{
NSLog(@"block ==== %s",__func__)
returnself;
};
}
此时就可以实现 person.eat3().run3(); 此时距离Masonry的样式就越来越接近了
那么我们知道 无论是eat3还是run3 的返回值是 返回Person类型的block,当我们 person.run3()时就是调用了run3返回回来的block,那么我们知道了 当我们返回的block中带有参数 是不是就可以实现person.run3(参数).eat3(参数);
于是:
- (Person *(^)(NSString *food))eat4{
return ^(NSString *food){
NSLog(@"吃了%@",food);
return self;
};
}
- (Person *(^)(int distance))run4 {
return ^(int distance){
NSLog(@"跑了%d米",distance);
return self;
};
}
这样就可以实现
NSLog(@"=========");
person.eat4(@"大骨头").run4(10000);
NSLog(@"=========");
person.run4(200000).eat4(@"小鱼");
了