Objective-Cのid型にはプロトコルへの準拠を明示する特殊な記法id<ProtocolName>
があります。
@property (nonatomic, assign) id <UITableViewDelegate> delegate;
プロトコル準拠や型チェックを実現する際の仕組みであり、iOS開発ではデリゲートを実現する際にもよく使われています。
今回はこの記法におけるid
と不等号<>
の間に空白を入れるべきか否かの問題を取り上げたいと思います。
id <Protocol> = nil; // 入れる派
id<Protocol> = nil; // 入れない派
標準ライブラリでは両方使われている
これはApple側でも意見が分かれているようで、標準フレームワークのヘッダファイルにおいては二種類の書き方が使われています。
// 割と古い時代からある
- (void)setDelegate:(id <NSTableViewDelegate>)delegate;
@property (assign) id<NSTabViewDelegate> delegate;
// 比較的最近追加された
@property (nonatomic, assign) id <UITableViewDelegate> delegate;
@property(nonatomic,assign) id<UITextViewDelegate> delegate;
追加された時代に関係なく両者のスタイルが混在しているようです。
割と適当ですね。
入力補完時は空白なしで自動入力される
ヘッダー上では空白ありで書かれていても、メソッド補完時には空白が取り除かれた状態で自動入力されます。
// ヘッダ上では「-(id <NSSharingServiceDelegate>)shar...」として定義されている
-(id<NSSharingServiceDelegate>)sharingServicePicker:(NSSharingServicePicker *)sharingServicePicker delegateForSharingService:(NSSharingService *)sharingService {}
公式ドキュメントでは空白が使われている
Appleの公式ドキュメントでは空白を入れているサンプルがほとんどですので本来はこちらが公式なのかもしれません。
公式リファレンスでは空白が使われていない
標準ライブラリ用のオンライン公式リファレンスでは空白が使われていません。
ブレますね。
- (void)setDelegate:(id<NSTableViewDelegate>)anObject
@property(nonatomic, weak, nullable) id< UITableViewDelegate > delegate
プロトコル採用時の記法では空白あり
クラスが特定プロトコルに準拠しているかどうかを明示する際にも同等の記法が使われています。こちらは全クラス共通して空白ありで書かれています。
@interface NSValue : NSObject <NSCopying, NSSecureCoding>
ジェネリクスでは空白が使われていない
Xcode7からNSArrayやNSDictionaryなどのコレクション向けにジェネリクスが利用できるようになりました。こちらは空白が省略されています。
+ (instancetype)arrayWithArray:(NSArray<ObjectType> *)anArray;
idでも空白なしで統一されていくか?
ジェネリクスでは空白なしが用いられていますし、リファレンスの方はid型も空白なしで統一されています。
標準ライブラリのヘッダファイルもそのうち空白なしで統一されていくと思いたいところですが、実際どうなるかはわかりません。
そもそもid型のそれはプロトコルや型チェック向けの機構であってジェネリクスではないわけですから、両者の違いを明確化するためにあえて空白を用いて区別するという考え方もありだと思うのです。
しかし結局の所は好みで選ぶしかないかもしれません。
実利主義的なプログラマは前者を取り、原理主義的なプログラマは後者を取ると良いかもしれません。私は前者が好みです。
まとめ
id<T> 記法 | id <T> 記法 | |
---|---|---|
ライブラリ/ヘッダファイル | ● | ● |
Xcode入力補完 | ● | |
公式ドキュメント | ● | |
公式リファレンス | ● | |
クラス宣言時のプロトコル準拠 | ● | |
ジェネリクス | ● |