Objective-Cでドット記法でメソッドを呼ぶ方法

[]でのメソッド呼び出しは悪くないのですが、メソッドチェインしたいときはどうしてもJavaとくらべて冗長なんですよね。でも工夫すればドット記法で任意のメソッドを呼ぶことができることに気づきました。

こんな感じ。

// ...
A *a = A.new;

a.foo(42).bar(@"hoge");

NSLog(@"a: %@", a); // a: A(_foo=42, _bar=hoge)

種明かしはこちら:

#import <Foundation/Foundation.h>

@interface A : NSObject

-(A*(^)(int))foo;
-(A*(^)(NSString*))bar;

@end

@implementation A {
    int _foo;
    NSString *_bar;
}

-(A*(^)(int))foo {
    return ^A*(int value) {
        _foo = value;
        return self;
    };
}
-(A*(^)(NSString*))bar {
    return ^A*(NSString *value) {
        _bar = value;
        return self;
    };
}

-(NSString*)description {
    return [NSString stringWithFormat: @"A(_foo=%d, _bar=%@)", _foo, _bar];
}

@end

int main() {
    A *a = A.new;

    a.foo(42).bar(@"hoge");

    NSLog(@"a: %@", a); // a: A(_foo=42, _bar=hoge)

    return 0;
}

つまり、-fooがブロックを返せば関数呼び出し演算子を適用できるというわけです。もちろんブロックの中はメソッドとスコープが同じでレシーバ(self)も参照できるので、本当にメソッドと同じことができます。受け取る引数も思いのまま。

懸念としては、クラス定義のコード量が増えることとブロックを間に挟むぶん少しオーバーヘッドがあること。ただメソッドチェインが意味を持つケース、たとえばActiveRecordライクなORMを作りたいときなどは使ってみてもいいハックかもしれないですね。