Xetius
Xetius

Reputation: 46844

How to create a typed stack using Objective-C

I can create a stack class quite easily, using push and pop accessor methods to an NSArray, however. I can make this generic to take any NSObject derived class, however, I want to store only a specific class in this stack.

Ideally I want to create something similar to Java's typed lists (List or List) so that I can only store that type in the stack. I can create a different class for each (ProjectStack or ItemStack), but this will lead to a more complicated file structure.

Is there a way to do this to restrict the type of class I can add to a container to a specific, configurable type?

Upvotes: 1

Views: 296

Answers (3)

Jacob Relkin
Jacob Relkin

Reputation: 163288

You can try something like this, although I do not recommend it:

@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

Upvotes: 2

Tommy
Tommy

Reputation: 100632

NSArray will take any object that implements the same protocol as NSObject; it doesn't need to be derived from NSObject. Because all dispatch in Objective-C is dynamic, inheritance isn't necessary for polymorphism.

Putting that aside, if you've implemented your own push and pop methods, you can easily test the incoming type using isKindOfClass or isMemberOfClass and reject those of the incorrect type.

To go further down, NSMutableArray documents which methods are conceptually primitive below the heading 'Subclassing Notes' in the Overview section at the top of the page. If you subclass NSMutableArray and alter addObject:, replaceObjectAtIndex:withObject: and insertObject:atIndex: to test the type of the incoming object then you can create a typed array.

Upvotes: 3

Marcelo Cantos
Marcelo Cantos

Reputation: 185962

Objective-C doesn't have generics or templates. Hence, idiomatic Objective-C code is written using NSObject * and id everywhere, casting as necessary.

Whatever you want to do, you should model it on the existing frameworks. See how NSArray, NSDictionary, NSSet, etc., are implemented, and follow suit.

Upvotes: 1

Related Questions