Как создать типизированный стек с помощью Objective-C

Однако я могу довольно легко создать класс стека, используя методы доступа push и pop к NSArray. Я могу сделать этот дженерик таким, чтобы он принимал любой класс, производный от NSObject, однако я хочу хранить в этом стеке только определенный класс.

В идеале я хочу создать что-то похожее на типизированные списки Java (список или список), чтобы я мог хранить только этот тип в стеке. Я могу создать отдельный класс для каждого (ProjectStack или ItemStack), но это приведет к более сложной файловой структуре.

Есть ли способ сделать это, чтобы ограничить тип класса, который я могу добавить в контейнер, определенным настраиваемым типом?


person Xetius    schedule 09.03.2011    source источник


Ответы (3)


Вы можете попробовать что-то вроде этого, хотя я не рекомендую это делать:

@interface TypedMutableStack : NSObject {
   Class type;
@private
   NSMutableArray *internal;
}

- (id) initWithType:(Class) type_;

@end

#define CHECK_TYPE(obj) if(![obj isKindOfClass:type]) {\
      [NSException raise:NSInvalidArgumentException format:@"Incorrect type passed to TypedMutableStack"];\
 }


@implementation TypedMutableStack

- (void) dealloc {
  [internal release];
  [super dealloc];
}

- (id) initWithType:(Class) type_ {
   self = [super init];
   if(self) {
      type = type_;
      internal = [[NSMutableArray alloc] init];
   }
   return self;
}

- (void) addObject:(id) obj {
   CHECK_TYPE(obj);
   [internal addObject:obj];
}

- (void) replaceObjectAtIndex:(NSUInteger) index withObject:(id) obj {
    CHECK_TYPE(obj);
    [internal replaceObjectAtIndex:index withObject:obj];
}

- (void) insertObject:(id) obj atIndex:(NSUInteger) index {
    CHECK_TYPE(obj);
    [internal insertObject:obj atIndex:index];
}

//...
@end
person Jacob Relkin    schedule 09.03.2011
comment
Это не сработает; NSMutableArray и NSArray являются абстрактными. Вы не можете подклассифицировать их и не предоставлять свой собственный механизм хранения. Самый простой способ сделать это — добавить NSMutableArray ivar и перейти к нему, а не к super. - person Dave DeLong; 10.03.2011
comment
Намного лучше. Для согласованности я бы также поставил NSInvalidArgumentException, но это только мой стиль. :) (таким образом не нужно придумывать новое имя исключения) - person Dave DeLong; 10.03.2011

NSArray примет любой объект, реализующий тот же протокол, что и NSObject; его не нужно получать от NSObject. Поскольку вся диспетчеризация в Objective-C является динамической, для полиморфизма наследование не требуется.

Отложив это в сторону, если вы реализовали свои собственные методы push и pop, вы можете легко протестировать входящий тип, используя isKindOfClass или isMemberOfClass и отклонить те, которые имеют неправильный тип.

Чтобы пойти дальше, NSMutableArray документирует, какие методы являются концептуально примитивными под заголовком «Примечания о подклассах» в разделе «Обзор» в верхней части страницы. Если вы создадите подкласс NSMutableArray и измените addObject:, replaceObjectAtIndex:withObject: и insertObject:atIndex: для проверки типа входящего объекта, вы сможете создать типизированный массив.

person Tommy    schedule 09.03.2011

В Objective-C нет дженериков или шаблонов. Таким образом, идиоматический код Objective-C везде пишется с использованием NSObject * и id, при необходимости приводя типы.

Что бы вы ни хотели сделать, вы должны моделировать это на основе существующих фреймворков. Посмотрите, как реализованы NSArray, NSDictionary, NSSet и т. д., и следуйте их примеру.

person Marcelo Cantos    schedule 09.03.2011