1

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?

1

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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

2 Comments

This won't work; NSMutableArray and NSArray are abstract. You can't subclass them and not provide your own storage mechanism. The easy way to do this is to add an NSMutableArray ivar and forward on to that instead of to super.
Much better. For consistency, I'd also throw an NSInvalidArgumentException, but that's just my style. :) (no need to invent a new exception name that way)
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.