iOS - Swift 和 OC 的简单链式编程

2017-05-04

链式编程就是将多个方法用点语法链接起来,让代码更加简洁,可读性更强

Swift 和 OC 的写法是有区别的

Swift 是直接返回对象本身,如

func name(_ name: String) -> Person {}

而OC 是返回一个 返回值为对象本身的 Block,如

-(Person * (^)(NSString *))nameEqule;

造成这种差别的原因是: 1.Swift中的点语法是可以直接用来使用方法的 2.OC中的点语法实际就是一个 getter/setter 方法,使用点语法,那么相当于使用 getter/setter 方法获取属性,因此采用和Swift类似的方法的话,只能用 [ ] 来调用,那么他的链式就表现为

[[[person nameEqule(@"Lily")] sexEqule(@"女")] ageEqule(12)];

缺乏美感,也不简洁。 但是返回 带参数,返回值为对象本身的 Block 的话,则可以表现为是一个 getter 方法,get一个 Block,然后在Block中传递参数。

###Swift 例子 重点在于方法返回的值为 对象本身,那么就可以在调用上一个方法的基础上接着调用方法,达到链式的效果

class Person {
    var name: String?
    var sex: String?
    var age: Int?
    
    init(closure: (Person) -> Void) {
        closure(self)
    }
    
    func name(_ name: String) -> Person {
        self.name = name
        return self
    }
    
    func sex(_ sex: String) -> Person {
        self.sex = sex
        return self
    }
    
    func age(_ age: Int) -> Person {
        self.age = age
        return self
    }
}

使用:

let person = Person.init { (person) in
    _ = person.name("Tom").age(12).sex("man")
}
print(person.name!,person.sex!,person.age!)  //输出 Tom man 12

如果不想要 返回值警告, 可以加上 @discardableResult

@discardableResult
func name(_ name: String) -> Person {
    self.name = name
    return self
}

那么就可以这么使用而不会有警告

let person = Person.init { (person) in
    person.name("Tom").age(12).sex("man")
}
print(person.name!,person.sex!,person.age!)  //输出 Tom man 12

###OC 例子

重点在于返回一个 返回值为对象本身的 Block

@interface Person : NSObject

@property(nonatomic, strong) NSString *name;
@property(nonatomic, strong) NSString *sex;
@property(nonatomic, assign) NSInteger age;

-(instancetype) init:(void (^)(Person *person)) block;

-(Person * (^)(NSString *))nameEqule;

-(Person * (^)(NSString *))sexEqule;

-(Person * (^)(NSInteger ))ageEqule;
@end

@implementation Person
-(Person *) init:(void (^)(Person *person)) block {
    self = [super init];
    if(self) {
        block(self);
    }
    return self;
}

-(Person * (^)(NSString * name))nameEqule {
    return ^(NSString * name) {
        self.name = name;
        return self;
    };
}

-(Person * (^)(NSString * sex))sexEqule {
    return ^(NSString * sex) {
        self.sex = sex;
        return self;
    };
}
@end

使用:

Person *person = [[Person alloc] init:^(Person *person) {
    person.nameEqule(@"Lily").sexEqule(@"女").ageEqule(12);
}];
NSLog(@"%@ %@ %ld",person.name,person.sex,(long)person.age); //输出 Lily 女 12