Programing

Objective-C에서 ID가 주어지면 어떤 유형의 객체를 가리키는 지 어떻게 알 수 있습니까?

lottogame 2020. 11. 16. 07:46
반응형

Objective-C에서 ID가 주어지면 어떤 유형의 객체를 가리키는 지 어떻게 알 수 있습니까?


Objective-C 초보자 질문. 다음 (가상) 코드가 주어지면 :

id mysteryObject = [anotherObject mysteriousMethod];

런타임에 클래스 mysteryObject무엇인지 어떻게 확인할 수 있습니까?


[mysteryObject class]

클래스 객체를 얻을 것입니다. 그러나 일반적으로 일부 프로토콜 또는 인터페이스에 대한 적합성 확인과 같은 OOPy를 수행하고 싶습니다.


isKindOfClass또는 사용할 수 있습니다.isMemberOfClass

예를 들면 :

if ([foo isMemberOfClass:[NSBar class]])


오브젝티브 C (또는 파이썬이나 루비)와 같은 동적 타입 언어에서는 자주하지 않는 원하는 그것이 개체의 유형을 알고. 객체가 보내려는 메시지에 응답하는지 여부를 생각하는 것이 종종 더 생산적입니다. 그렇다면 인스턴스화하는 클래스를 신경 쓰지 않아야하며 그렇지 않은 경우 인스턴스의 유형에 관계없이 케이스를 처리해야합니다. 이것은 "오리 타이핑"으로 알려져 있습니다. 만약 그것이 오리처럼 꽥꽥 거리면 그것은 오리입니다.

다음과 같이 객체가 특정 메시지 (Objective-C에서 선택기)에 응답하는지 여부를 테스트 할 수 있습니다.

if([mysteryInstance respondsToSelector:@selector(messageIWishToSend)]) {
  [mysteryInstance messageIWishToSend];
} else {
  //handle case where instance doesn't respond to the desired message
}

개별 선택자를 테스트하는 것보다 더 나은 것은 @protocol클래스에 사용하려는 API를 설명 하는를 정의하는 것 입니다.

// MyProtocol.h
@protocol MyProtocol
- (void)methodInMyProtocol;
@end

//MyClass.h

#import "MyProtocol.h"

@interface MyClass <MyProtocol> {

}
- (void)methodInMyProtocol;
@end

인스턴스가 다음 MyProtocol과 같은 프로토콜을 구현하는지 테스트 할 수 있습니다 .

if([mysteryInstance conformsToProtocol:@protocol(MyProtocol)]) {
  [mysteryInstance methodInMyProtocol];
} else {
  // ...
}

이러한 작업 방식은 Java 또는 C ++와 같이 정적으로 형식화 된 언어를 사용하는 사람들에게 종종 불편합니다. 컴파일러 검사 유형을 풉니 다. 하지만 동적 타이핑을 사용하면 테스트를 포함하여 테스트를 포함하여 많은 작업을 쉽게 수행 할 수 있습니다. 테스트 할 때 인스턴스를 가짜로 쉽게 바꿀 수 있기 때문입니다. 따라서 동적 언어 접근 방식은 더 많이 테스트하고 유형에 대해 걱정하는 것입니다. 당신은 좋은 단위 테스트 커버리지를 가지고 있지 않습니까?

런타임에 인스턴스의 클래스를 결정해야하고 실제로 그럴 필요가없는 -[NSObject isKindOfClass:]경우 인스턴스가 클래스 또는 하위 클래스 -[NSObject isMemberOfClass:]의 인스턴스인지 여부를 테스트 하거나 인스턴스가 있는지 여부를 테스트하는 데 사용할 수 있습니다. 특정 클래스의 인스턴스입니다. Class반환 값으로 객체를 직접 검사 할 수 있으며 .NET -[NSObject class]을 사용하여 인스턴스 클래스의 문자열 이름을 가져올 수 있습니다 NSStringFromClass([mysteryInstance class]).


@protocol에 정의 된 메서드와 함께 사용할 때 id로 다시 캐스팅해야한다는 것을 알았습니다.

예를 들어 self.listeners는 id의 배열입니다.

이렇게하면 ....

for(id<PropertyListener> listener in self.listeners) {        
    if ( [ [ listener class]  respondsToSelector:@selector(propertyChanged:propertyName:)]) {

"선택자 '클래스'에 대해 알려진 인스턴스 메서드가 없습니다."라는 오류가 발생합니다. 그래도 이드를 이드에서 캐스트하면 작동이 ... 왜인지 모르겠다.

[ ((id)listener) class] respondsToSelector .... 

여기에 전체 루프가 있습니다 ...

for(id<PropertyListener> listener in self.listeners) {        
    if ( [ [ ((id)listener) class]  respondsToSelector:@selector(propertyChanged:propertyName:)]) {
        [listener propertyChanged: self propertyName:@"thePropName"];
    } else {
        [listener propertyChanged: self];
    }
}

참고URL : https://stackoverflow.com/questions/1123485/in-objective-c-given-an-id-how-can-i-tell-what-type-of-object-it-points-to

반응형