2011-10-27 3 views
11

Objective-C에는 Subclass 구현이 있는지 클래스에 요청하는 방법이 있습니다.Objective-C : 수퍼 클래스에서 서브 클래스 목록 가져 오기

나는 여러 하위 클래스가있는 Base 클래스를 사용합니다. 모든 하위 클래스를 반복하고 각 클래스에 대해 클래스 선택기를 수행하고 싶습니다.

편집 :

나는 특정 유형의 데이터를 처리 할 수있는 클래스의 집합이있다. 각 프로세서는 각 프로세서에 필요한 메서드를 제공하는 기본 클래스의 하위 클래스입니다.

각 클래스는 처리 할 수있는 데이터를 알고 있으며 일부 클래스는 특정 유형의 데이터를 다른 클래스보다 잘 처리 할 수 ​​있습니다.

각 클래스에 대한 응답을 제공하는 팩토리 클래스에 대한 클래스 메소드를 갖고 싶습니다. 예를 들어 해당 데이터를 처리 할 수 ​​있고 얼마나 처리 할 수 ​​있는지 표시 할 수 있습니다.

그러면 공장에서는 어떤 클래스가 데이터를 가장 잘 처리 할 수 ​​있는지에 따라 인스턴스화 할 클래스를 결정하게됩니다.

2009 년부터이 질문을 발견했습니다 (게시하기 전에 검색했지만 아무것도 찾지 못했습니다) Discover subclasses of a given class in Obj-C.

편집 2는 :

+ (void)load 방법은 내가 무엇을 찾고에 대한 완벽한 솔루션 것으로 보인다. 그래서 지금 다음과 같습니다 :

+ (void)registerSubclass:(Class)subclass { 
    NSLog(@"Registered %@", subclass); 
} 

내 기본 클래스에서 이것은 내 subs입니다.

+(void)load { 
    [BaseSwitch registerSubclass:[self class]]; 
} 

이제 각 하위 클래스에 대한 디버그 메시지가 표시됩니다.

내 다음 질문은 (아마도 바보 같은), registerSubclass 메소드에 등록 된 클래스를 저장하는 방법은 무엇입니까? 나중에 읽을 수있는 클래스 변수를 가질 수있는 방법이 있습니까?

편집 3 : 모두가 말하고 완료 후 여기에 다음 날 떠난 A simple, extensible HTTP server in Cocoa

몇 가지 예제 코드를 찾을 수

은 아주 간단 보인다. 하지만 나중에 참조 할 수 있도록 여기에 넣을 것이라고 생각했습니다.

@implementation BaseSwitch 

static NSMutableArray *registeredSubclasses; 

+ (void)registerSubclass:(Class)subclass { 
    if (registeredSubclasses == nil) { 
     registeredSubclasses = [[NSMutableArray alloc] init]; 
    } 

    [registeredSubclasses addObject:subclass]; 

    NSLog(@"Registered %@", subclass); 
} 

+ (void)logSubclasses { 
    for (int i = 0; i < [registeredSubclasses count]; i++) { 
     NSLog(@"%@", [registeredSubclasses objectAtIndex:i]); 
    } 
} 

@end 

여러분의 의견을 보내 주셔서 감사합니다. 나는 다른 질문이 나오면 며칠 동안 답변을 드릴 수 없습니다.

+1

링크 된 질문에서 마이크의 제안을 사용할 수없는 이유는 무엇입니까? 수퍼 클래스에 데이터 유형에 대한 클래스를 등록하기위한 API를 노출시키고 각 서브 클래스가 해당 API를 사용하여 수퍼 클래스에 처리 할 수있는 데이터 유형을 알리십시오. 수퍼 클래스 대신 다른 클래스에서 내보낼 수도 있습니다. –

+0

@Bavarious, 아마도 내가 갈 방법입니다. 그러나 다른 방법이 있는지 알고 싶습니다. – Littlejon

+3

당신은 수업을 등록 된 상태로 멀리하는 것이 훨씬, 멀리 떨어져 있습니다. 동적 발견은 매력적이지만 Objective-C는 그러한 패턴을 위해 설계되지 않았습니다. 명시 적 등록은 또한 모든 등록자의 목록을 산출하기 위해 검색 할 수있는 한 자리 또는 한 개의 간단한 문자열이 있다는 이점이 있습니다. – bbum

답변

-5

클래스의 하위 클래스는 절대로 나열 할 수 없습니다. (거의) 모든 프로그래밍 언어. 이것은 객체 지향 프로그래밍의 기본 속성 중 하나입니다.

개체 모델을 변경하는 것이 좋습니다.

추상 클래스와 다른 하위 클래스를 만드는 것이 좋겠지 만 추상 클래스의 하위 클래스에는 액세스하면 안됩니다.서브 클래스를 등록하고 필요할 때 적절한 항목을 선택하는 다른 객체 (Factory 클래스)를 만들어야합니다.

클래스 자체에서 클래스를 효율적으로 등록 할 수는 없습니다. 클래스 코드를 실행하려면 먼저 클래스를로드해야합니다. 즉, 다른 클래스에서 헤더를 가져와야한다는 것을 의미합니다. 즉, 실제로 헤더를 가져 와서 클래스를 등록한다는 의미입니다. 두 가지 해결책이 있습니다

  1. 귀하의 공장 클래스는 모든 서브 클래스 (중 컴파일시에 또는 일부 구성 파일을 읽는)의 이름을 알고있다.
  2. 팩토리 클래스에는 누구나 등록 할 클래스의 이름을 전달할 수있는 메소드가 있습니다. 이것은 외부 라이브러리가 새로운 서브 클래스를 등록하기를 원한다면 올바른 해결책입니다. 그런 다음 하위 클래스 등록 코드를 라이브러리의 기본 헤더에 넣을 수 있습니다.
+5

클래스의 가능한 모든 하위 클래스를 나열 할 수는 없지만 지정된 시점에 지정된 프로그램 내에있는 하위 클래스를 나열하지 못하게하는 OOP의 속성은 없습니다. ObjC에서는,'objc_getClassList()'로 이것을 수행 한 다음 클래스를 인트로 스펙 트할 수 있습니다. 좋은 생각은 아니지만 OOP에 관한 어떤 것도 그것을 금지하지 않습니다. –

+1

당신은 맞습니다. 그러나 확실히 그것은 수퍼 클래스에서 OOP의 원칙에 위배됩니다 :) 그러나 클래스는 어딘가에로드되어야하고 클래스를로드하기 위해 클래스의 이름 (또는 정의 된 파일)을 알아야합니다. – Sulthan

+0

@Sulthan 그것은 "원리에 어긋나는"것이고, 그들이 선언 된 파일이 중요한 이유는 무엇입니까? 런타임에는 클래스 목록이 있으므로 원하는대로 쿼리 할 수 ​​있습니다. 내가 사용 해본 모든 동적 언어에는이 기본 기능이 있습니다. –

10

이 기능은 당신에게 클래스의 모든 서브 클래스를 제공합니다

#import <objc/runtime.h> 

NSArray *ClassGetSubclasses(Class parentClass) 
{ 
    int numClasses = objc_getClassList(NULL, 0); 
    Class *classes = NULL; 

    classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses); 
    numClasses = objc_getClassList(classes, numClasses); 

    NSMutableArray *result = [NSMutableArray array]; 
    for (NSInteger i = 0; i < numClasses; i++) 
    { 
    Class superClass = classes[i]; 
    do 
    { 
     superClass = class_getSuperclass(superClass); 
    } while(superClass && superClass != parentClass); 

    if (superClass == nil) 
    { 
     continue; 
    } 

    [result addObject:classes[i]]; 
    } 

    free(classes); 

    return result; 
} 

Cocoa with Love에서 촬영.

+0

은 ARC에서 던지는 오류입니다. – ravoorinandan

+0

@ravoorinandan 나는 그것이 ARC를 위해 컴파일되지 않는다는 것을 의미한다고 생각한다. ARC 지원을 위해 업데이트했습니다. – ThomasW

+0

@ ThomasW 감사합니다. 그것을 시도하고 알려 드리겠습니다. :) – ravoorinandan

관련 문제