instance type

Objective-C는 (논란의 여지는 있지만) 지금도 급속히 발전하고 있는 언어이다. ARC, 오브젝트 리터럴, 서브스크립팅, 블럭과 같은 기능들이 최근 몇 년 사이에 추가되었고, 이런 것들은 프로그래밍 방식 자체를 바꾸고 있다. 이런 모든 혁신은 애플의 수직 통합의 철학이 내놓은 결과물이다. 애플이 칩 디자인에 공을들여 하드웨어에 있어서 공격적인 경젱을 할 수 있게 된 것 만큼이나, 그들은 LLVM에 투자하여 페이스를 맞추고 있다.

alloc이나 init과 같은 생성 메소드들은 모두 id 타입의 객체를 내놓지만, Xcode는 이런 객체들에 대한 타입체크를 제대로 하고 있다. 어떻게? 코코아에서 alloc이나 init이라는 단어가 들어간 메소들은 모두 수신자 클래스의 인스턴스 객체를 내놓는다. 즉, 수신자와 연관된 타입을 리턴한다는 것이다. 대신에 클래스의 컨스트럭터 메소드들은 이러한 타입체킹을 하지 않는다. 즉, alloc, init에 의한 리턴 객체들만 이것이 가능하다.

예를 들어:

[[[NSArray alloc] init] mediaPlaybackAllowsAirPlay]; 

라고 입력하면, Xcode는 즉각 NSArray의 인터페이스에는 정의되지 않은 셀렉터라며 에러 표시가 뜬다. 하지만,

[[NSArray array] mediaPlaybackAllowsAirPlay]; 

는 (물론 실행시에는 오류가 나겠지만) Xcode는 어떠한 에러도 검출하지 않는다. (이는 Xcode 5에서부터 가능해졌다) 왜냐하면 alloc-init 컨벤션은 연관 타입을 리턴하기 때문에 컴파일타임에 타입체킹이 가능해진다. 하지만 팩토리 메소드들는 단지 id 객체를 리턴하므로 이것이 가능하지 않다.

id는 타입을 확정하지 않은 유연함을 제공한다. 그리고 리턴 타입을 강제로 캐스팅하는 경우, ((NSArray *)[[NSArray alloc] init])는 서브클래스와는 또 제대로 어우러지기 힘들다.

instancetype은 연관 객체를 의미하는 일종의 타입 플레이스홀더이다. 예를 들어

@interface Person : NSObject
+ (instancetype)personWithName:(NSString *)name;
@end

이라고 인터페이스를 선언한 클래스에서는 컴파일러는 이 메소드를 이용해 생성한 객체가 Person 클래스의 인스턴스라는 사실을 알게 된다.