Objective-C: Получить список подклассов из суперкласса

В Objective-C есть ли способ спросить класс, есть ли какие-либо реализации подкласса.

У меня есть класс Base, который имеет несколько подклассов. Я хотел бы пропустить все подклассы и выполнить селектор классов для каждого из них.

Edit

У меня есть набор классов, которые могут обрабатывать определенные типы данных. Каждый из подклассов подклассифицирует базовый класс, который предоставляет методы, необходимые каждому процессору.

Каждый класс знает, какие данные он может обрабатывать, а некоторые классы могут обрабатывать определенные типы данных лучше других.

Я хотел бы иметь метод класса для каждого класса, который предоставит ответ обратно классу factory, который говорит "да", я могу обработать эти данные и дать представление о том, насколько хорошо он может обработать его.

factory затем примет решение о том, какой класс должен создать экземпляр на основе того, какой класс говорит, что он может обрабатывать данные лучше.

Я также нашел этот вопрос с 2009 года (я искал, прежде чем опубликовал это, но ничего не нашел) Откройте подклассы данного класса в Obj-C.

Изменить 2:

Метод + (void)load выглядит идеальным решением для того, что я ищу. Итак, теперь у меня есть следующее:

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

В моем базовом классе это мои subs.

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

Теперь отображается сообщение об отладке для каждого из подклассов.

Мой следующий вопрос (вероятно, глупый), как хранить классы, которые регистрируются в методе registerSubclass. Есть ли способ иметь переменную класса, которую я могу прочитать позже?

Изменить 3:

Нашел здесь некоторый пример кода Простой, расширяемый HTTP-сервер в 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

Вы никогда не сможете перечислить подклассы класса. В (почти) любом языке программирования. Это одно из основных свойств объектно-ориентированного программирования.

Рассмотрим изменение объектной модели.

Возможно, вам нужно создать абстрактный класс и разные подклассы, но вы не должны обращаться к подклассам из абстрактного класса. Вы должны создать еще один объект (класс Factory), который регистрирует подклассы и при необходимости выбирает подходящий.

Обратите внимание, что вы не можете эффективно зарегистрировать класс из самого класса. Для кода класса, который должен быть выполнен, сначала должен быть загружен класс. Это означает, что вам нужно импортировать заголовок в какой-то другой класс, а это значит, что вы фактически регистрируете класс, импортируя его заголовок. Существует два возможных решения:

  • Класс factory должен знать имена всех подклассов (во время компиляции или чтения некоторого файла конфигурации).
  • В классе factory есть метод, с помощью которого любой может передать имя зарегистрированного класса. Это правильное решение, если вы хотите, чтобы внешние библиотеки регистрировали новый подкласс. Затем вы можете поместить код регистрации подкласса в главный заголовок библиотеки.

Ответ 2

Эта функция дает вам все подклассы класса:

#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 с любовью.