2009-11-27 3 views
9

주어진 클래스의 서브 클래스가 런타임에 발견되는 방법이 있습니까?Obj-C에서 주어진 클래스의 서브 클래스를 발견하십시오

편집 : 대답에서 지금까지 나는 내가하고 싶은 것을 조금 더 명확히해야한다고 생각합니다. 나는 이것이 코코아에서 일반적인 관행이 아니며 약간의주의 사항이있을 수 있음을 알고 있습니다.

저는 동적 생성 패턴을 사용하여 파서를 작성하고 있습니다. 기본적으로 파서 인스턴스는 스택을 처리하고 특정 계산을 수행하는 방법을 알고있는 객체를 인스턴스화합니다.

MYCommand 클래스의 모든 하위 클래스를 가져올 수 있다면 예를 들어 사용 가능한 명령 목록을 사용자에게 제공 할 수 있습니다. 또한 5 장의 예제에서 파서에는 +, -, * 및 /와 같은 연산자를 사용할 수 있도록 대체 사전이 있습니다. (그들은 MYAddCommand, 등등에 매핑됩니다.) 저에게는이 정보가 MyCommand 하위 클래스에 속한 것 같았습니다. 파서 인스턴스가 아닌 것은 동적 생성이라는 아이디어를 다소 상실했기 때문입니다.

답변

13

오히려 왜 두 문제를 분할하지, 자동으로 MYCommand의 모든 서브 클래스를 등록하려고보다 더?

먼저 클래스를 등록하기위한 API (예 : +[MYCommand registerClass:])를 제공하십시오.

그런 다음 모든 하위 클래스가 자동으로 자신을 등록 함을 의미하는 MYCommand에 코드를 작성하십시오. 뭔가 같이 : 방법 :

@implementation MYCommand 
+ (void)load 
{ 
    [MYCommand registerClass:self]; 
} 
@end 
+0

이것은 실제로 갈 수있는 올바른 방법입니다. 특히 문서에서는 클래스의'+ load' 메소드가 모든 수퍼 클래스의'+ load' 메소드 후에 호출된다는 것을 언급하고 있기 때문에 특히 그렇습니다. 답변을 제공하는 다른 사람들에게 많은 감사를드립니다. –

+2

MyCommand의 서브 클래스는 수퍼 클래스에서 + load를 호출하지 않습니다. + load는 그것을 구현하는 클래스에서만 호출됩니다. –

+0

누군가가 나를 바로 잡는 데 오랜 시간이 걸렸습니다. 나는 일반적으로 자동 등록이 나쁜 생각이고 대신에 좀 더 수동으로 처리해야한다는 답변에 동의한다. –

19

아니요, 아니요. 그러나 런타임에 등록 된 모든 클래스 목록을 가져올 수 있으며 직접 수퍼 클래스에 대해 해당 클래스를 쿼리 할 수 ​​있습니다. 이것으로 상속 트리의 상위 조상을 찾을 수는 없다는 것을 명심하십시오.

objc_getClassList()을 사용하면 런타임에 등록 된 Class 개체 목록을 가져올 수 있습니다. 그런 다음 해당 배열을 반복하고 해당 Class 객체에 [NSObject superclass] 객체를 호출하여 수퍼 클래스 'Class 객체를 가져올 수 있습니다. 어떤 이유로 든 수업에서 NSObject을 루트 클래스로 사용하지 않으면 대신 class_getSuperclass()을 사용할 수 있습니다.

당신이 이런 종류의 발견을해야 할 필요가 있다고 느끼는 경우 응용 프로그램의 디자인에 대해 잘못 생각하고 있음을 언급해야합니다. 대부분 Objective-C 런타임에 대한 내성 검사를 포함하지 않고 수행하려는 작업을 수행하는 또 다른보다 일반적인 방법이 있습니다.

+7

나는 그것을 더 강하게 말할 것이다. 프로덕션 코드에서이 작업을 수행해야한다고 생각되면 잘못 처리했을 가능성이 큽니다.하향식 상속 내성 검사는 극히 드문 일이며 런타임이이를 직접 지원하지 않는 이유입니다. 너 뭐하려고? – bbum

+0

@bbum 내가하려는 일에 대한 설명을 추가했습니다. 아직도 내가 아주 잘못하고 있다고 생각하니? 하위 클래스를 찾지 않고이 작업을 수행하는 또 다른 방법을 생각해보기 힘들다. –

4

마르크와 bbum 돈에 그것을 쳤다. 이것은 대개 좋은 생각이 아닙니다.

그러나, 우리는이 작업을 수행 우리의 CocoaHeads 위키 코드가 : http://cocoaheads.byu.edu/wiki/getting-all-subclasses

+1

또 다른 경고; 이런 종류의 일을 할 때 클래스가 초기화되지 않았을 수도있는 순서로 + 초기화 될 것입니다. 이것은 문제를 일으키지 않아야하지만 때로는 버전간에 변경 될 수있는 시스템 클래스의 종속성으로 인해 발생합니다 ... – bbum

+0

링크 된 코드에 대한 설명은이 접근 방식이'+ 초기화 '를 호출하지 않는다고 말합니다. 아직 시도하지 않았던 것 같습니다. –

0

-subclassNamesForClass을 포함 내 런타임 브라우저 프로젝트 here 코드가있다. RuntimeReporter.[hm] 파일을 참조하십시오.

+0

고마워, 내 벨트에 추가 할 수있는 흥미로운 도구. 이 특별한 경우에 대해서는 마이크의 접근 방식을 사용하겠습니다. –

+0

@NSResponder에 의해 게시 된 링크가 깨졌습니다. 클래스 계층 구조를 순환하는 방법을 찾는 사람들을 위해 비슷한 접근 방식을 사용하는 [클래스 계층 구조 로거] (https://github.com/sebaven/class-hierarchy-logger)를 작성했습니다. 서브 클래스 계층을 반복하는 f}에 대해 더 많은 통찰력이 필요하면 유용 할 수 있습니다. 도움이되기를 바랍니다! –

3

또 다른 방법은 매트 Gallagher가 his blog에 게시했습니다.

관련 문제