2013年11月20日 星期三

instancetype 與 id

Would it be beneficial to begin using instancetype instead of id?

需要ARC環境, 這部分我還不太懂, 引用StackOverFlow回答者原文
This was necessary for ARC. This is described in Clang Language Extensions Related result types.

在繼續講之前補充個寫文章才爬到的知識... 引用自NSHipster
In Cocoa, there is a convention that methods with names like alloc, or init always return objects that are an instance of the receiver class. These methods are said to have a related result type.
Class constructor methods, although they similarly return id, don't get the same type-checking benefit, because they don't follow that naming convention.
如果是Instance Method, 若是返回id, 則return的物件形態會是Receiver Class
如果是Class Method, 若是返回id, 則return的物件形態會無法判別

再來解釋id與instancetype差異
id不會做形態判別
instaancetype做形態判別

舉例子來說
FooBar.h
#import <Foundation/Foundation.h>

@interface Foo : NSObject
+ (id)buildInstance;
- (id)init;
@end

@interface Bar : Foo
- (void)doSometingElse;
@end

FooBar.m
#import "FooBar.h"

@implementation Foo
+ (id)buildInstance {
    return [[self alloc] init];
}
- (id)init {
    return [super init];
}
@end

@implementation Bar
- (void)doSometingElse {
    NSLog(@"%@", NSStringFromSelector(_cmd));
}
@end

測試
//Class Method, id返回形態無法判斷
[[Foo buildInstance] doSometingElse];
    
//Instance Method, id返回形態為class形態
[[[Foo alloc] init] doSometingElse];

第二段無意外在編譯前就會有Error, init返回形態會是Class, 也就是Foo
而Foo並沒有doSometingElse此method

再來看比較重要的第一段, 把第二段的程式註解, 編譯過得去, 但實際執行之後就會當掉
而理由就是上面提到, Class Method若返回形態是id, 會無法判別Receiver Class為何
解決方式就是把 +(id)buildInstance 改為 +(instancetype)buildInstance
就會看到在編譯之前就出現如同第二段一樣的錯誤


最後根據StackOverFlow下面有篇文章的結論哪邊可以把id改用為instancetype
You should hesitate before writing a message that returns id. Ask yourself: Is this returning an instance of this class? If so, it's an instancetype.
如果返回的id形態為此Receiver Class, 則可把id改用instancetype

沒有留言:

張貼留言