Objective-C: получить список подклассов из суперкласса - PullRequest
11 голосов
/ 28 октября 2011

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

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

Редактировать :

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

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

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

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

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

Edit 2 :

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

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

В моем базовом классе это мои подпрограммы.

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

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

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

Редактировать 3 :

Здесь вы найдете пример кода Простой, расширяемый HTTP-сервер вКакао

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

@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

Спасибо за любые предложения, я оставлю вопрос без ответа еще на пару дней, если возникнет что-то еще.

Ответы [ 2 ]

10 голосов
/ 13 апреля 2014

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

#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;
}

Взято из Какао с любовью .

0 голосов
/ 31 октября 2011

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

Рассмотрите возможность изменения вашей объектной модели.

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

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

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