2011-10-26 2 views
36

나는 알 수없는 값 객체를 만들고 싶을 때 id를 사용한다는 것을 알고있다. 그러나, 나는 모든 객체가 NSObject의 서브 클래스 일 때 런타임 동안 값을 결정하는 이유를 Apple이 선택하게 된 이유가 궁금합니다. 그래서 id delegate 대신에 우리는 사용할 수 있었다 NSObject *delegate 누군가는 이유를 알고 있습니까? 감사.NSObject를 사용할 수있는 이유는 무엇입니까?

+1

NSProxy는 코코아가 제공하는 또 다른 루트 클래스입니다. –

+0

NSObject에 isa 포인터가 포함되어 있지만 ID에는 없습니다. http://stackoverflow.com/a/19634973/944634 –

+0

무엇을 권자? id는 isa 포인터입니다. http://stackoverflow.com/questions/1990695/in-cocoa-how-is-the-id-type-defined – TheAmateurProgrammer

답변

39

id은이 유형을 지우며 "이 객체는 번역에서 볼 수있는 선택자에게 응답합니다"라고하는 것과 같습니다. 물론 유형을 지울 때 (그리고 유형을 변환 할 때) 프로그램이 올바른지 확인해야합니다.

유형이 NSObject 인 경우, 다음 말을 컴파일러가 "NSObject의이 선택에 응답하지 않을 수 있습니다"선택기는 NSObject의의 인터페이스 또는이 채택 프로토콜에 선언되지 않은 경우. 이 경우에는 유형 변환을 추가하여 원하는 유형으로 변환 할 수도 있습니다.

엄격한/올바른 형식을 사용하면 컴파일러에서 시작하여 도움을받을 수 있습니다. ObjC는 매우 동적 인 언어이기 때문에 좋습니다.

id은 특히 컬렉션 유형을 사용 (또는 작성) 할 때 유용합니다. 새 루트 유형을 정의하지 않으면 (NSObject에서 상속하지 않음) 객체를 추가해도 문제가되지 않습니다. 컬렉션에서 값을 얻으려면 우리가 기본 클래스 (NSObject)가 아닌 다른 것으로 사용하려면 유형 변환이 필요합니다.

Objective-C는 제네릭을 지원하지 않습니다. 예를 들어 NSArrayNSString으로 선언 할 수 없습니다. NSArrayNSString으로 채우고 형식 안전성이 유지되지 않을 때보다 자연스러운 서체 스타일의 경우 id을 전달하면됩니다 (제네릭).

그럼 실제 코드로 확장 해 보겠습니다.

예 A

NSString * string = [array objectAtIndex:0]; // << trust me (via id) 
return [string length]; 
-or- 
return [[array objectAtIndex:0] length]; // << trust me (via id) 

예 B 지금

그리고 옳은 일이기 때문에 이제 id를 사용할 수없는 우리는 우리의 모든 컴파일러 경고를 수정 가정 해 봅시다 :

NSString * string = (NSString*)[array objectAtIndex:0]; // << typecast == trust me 
return [string length]; 
-or- 
return [(NSString*)[array objectAtIndex:0] length]; // << typecast == trust me 

id 그것의 값은 런타임에, NSObject를 수행하지 마십시오. ObjC 객체는 암시 적 프로모션을 수행하지 않고 공식 프로모션없이 포인터를 캐스트합니다.당신의 예제에 관련

, 실제로 프로토콜 NSObjects 나의 대표 및 매개 변수를 선언

NSObject<MONShapeDelegate>* delegate; 
+0

다른 컴파일러에서 사용했던 것과 다를 수 있지만 내가 아는 한 선언 한 경우 NSObject 형식의 컴파일러는 객체가 SomeProtocol의 모든 메서드를 구현한다고 가정합니다. – Aberrant

+0

@Aberrant 대리자 메서드가 옵션 인 경우 개체가 선택기에 응답하는지 확인하는 것은 호출자 *에게 달려 있습니다. – justin

+0

저는 그것이 컴파일러가 구현되었다고 가정 한 이유입니다. 그렇지 않은 경우 컴파일러는 런타임에 객체가 응답할지 여부를 확신 할 수 없으므로 optionals는 항상 경고를 발생시킵니다. – Aberrant

2

모든 개체가 잘못이다 NSObject의

의 서브 클래스입니다. 루트 클래스로 아무것도 확장하지 않는 객체를 만들 수 있습니다.

아마도 id가 도입 된 이유 일 것입니다.

11

모든 객체가 잘못된 진술이다 NSObject의

의 서브 클래스입니다. NSObject에서 상속받지 않는 객체를 생성 할 수 있습니다. 그것은 정말로 권장되지 않지만 가능합니다.

NSProxy은 NSObject에서 상속받지 않습니다.

+3

이것은 내 대답의 복제품입니다! –

+1

미안 :/대답이 없을 때 썼다, 펀치 날 때려 눕혔다 ... 힘들지도 않고 투표를위한 필요도 없다 ... 또한, NSProxy를 언급하지 않았다. – Jasarien

+1

스택과이 답변이 맨 아래에 있다면 @Jasarien이 먼저 대답했습니다.) – beryllium

3
typedef struct objc_object { 
    Class isa; 
} *id; 

위의 내용은 Objective-C 언어의 id의 실제 정의입니다. Objective-C 런타임 시스템은 idClass에 구축됩니다. NSObject 나 일반적인 수퍼 클래스와 관련된 것은 없습니다.

NSObject의 클래스

NSObject의

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-SW3

는 슈퍼 클래스가없는 그래서 루트 클래스이며,. Objective-C 객체와 객체 상호 작용을위한 기본 프레임 워크 인 을 정의합니다. 에서 상속받은 클래스의 클래스 및 인스턴스에 객체로 동작 할 수있는 기능을 부여하고 런타임 시스템과 협업합니다.

다른 클래스의 특별한 동작을 상속 할 필요가없는 클래스는 NSObject 클래스의 서브 클래스로 만들어야합니다. 클래스의 인스턴스는 최소한 Objective-C 객체처럼 동작 할 수 있어야합니다. NSObject 클래스에서이 기능을 상속하는 것은 새 클래스 정의에서 을 다시 작성하는 것보다 훨씬 간단하고 훨씬 더 신뢰할 수 있습니다. 원래 C하지 C++ (또는 다른 더 엄격한 입력 언어)이기 때문에 생각

이입니다.

관련 문제