2

I'm running into some trouble implementing a simple super/sub class scheme. I declare an NSMutableDictionary in the superclass, and am trying to access it in a subclass, but it only returns null. Any help would be appreciated.

@interface RootModel : NSObject <Updatable, TouchDelegate>
@property (nonatomic) NSMutableDictionary *gameValues;
@end

@interface SubclassModel : RootModel
@end

@implementation RootModel

- (id)initWithController:(id)controller {
    if ((self = [super init])) {
        _controller = controller;

        _gameValues = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                       [NSNumber numberWithFloat:300.0f], KEY_JUMP_VELOCITY,
                       [NSNumber numberWithFloat:49.47f], KEY_GRAVITY,
                       [NSNumber numberWithFloat:0.25f], KEY_JUMP_TIME_LIMIT,
                       nil];

        NSLog(@"%@", _gameValues);

    }
    return self;
}

@implementation SubclassModel

- (id)init{
    if ((self = [super init])) {
        // This NSLog prints "(null)" if using super.gameValues or self.gameValues, why?
        NSLog(@"subclass: %@", super.gameValues);

    }
    return self;
}
@end

What am I doing wrong?

Clev3r
  • 1,568
  • 1
  • 15
  • 28
  • Refer this [post](http://stackoverflow.com/questions/5588799/objective-c-how-do-you-access-parent-properties-from-subclasses) for descrption and detail, as will remove that NSObject from the first line of your code. – Dipen Panchasara Apr 02 '13 at 17:40

2 Answers2

2

As Catfish_Man answered, your init method needs to call [super initWithController:]. However you seem to show a misunderstanding of the class/super class inheritance model with your comment:

My superclass is initialized by another controller class. Any calls to the super's properties (which were initialized in initWithController:) are valid (they return values, not null).

When you create an instance of your SubclassModel then that instance has as part of itself a RootModel instance. That RootModel instance is not shared with any other instance of SubclassModel or RootModel.

So if "another controller class" creates and initialises and instance of RootModel, which in turn displays your NSLog output, then that is a totally different object to your SubclassModel instance - and the RootModel that is part of your SubclassModel instance is not initialised, as you don't call [super initWithController:], hence you NSLog in SubclassModel shows nil.

CRD
  • 52,522
  • 5
  • 70
  • 86
  • So it would be a better idea to have a singleton RootModel, so each superclass does not init its own version of the model? – Clev3r Apr 02 '13 at 18:06
  • @Clever - No. A singleton is a different concept. When you declare a subclass, say `B`, of a class `A`, then *every* instance of `B` has its *own* `A`. That is the inheritance model. If you are unsure about this you need to read up on how subclass inheritance works, this model is fundamental to Obj-C (and most OO languages) and you need to understand it. – CRD Apr 02 '13 at 18:11
  • Thanks for the reminder. Apparently it's been too long. However, now that you have clarified this– I absolutely do not want every subclass to have it's own A. – Clev3r Apr 02 '13 at 18:15
  • 1
    @Clever - in that case `SubclassModel` should not be a subclass of `RootModel` at all; instead it should maintain a reference (in an instace variable) to a shared model and its initialisation method would be something like `- (id) initWithSharedRootModel:(RootModel *)sharedRootModel`. *(It looks like you might be trying to follow a delagation-based rather than inheritance-based model, if so you must implement it yourself as Obj-C is inheritance based. If this makes no sense, just ignore!)* – CRD Apr 02 '13 at 18:32
1

Your subclass init method needs to call [super initWithController:], since that's where the actual initialization happens.

(or the superclass initWithController: needs to call [self init], and you need to move the initialization work you're relying on to init)

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
Catfish_Man
  • 41,261
  • 11
  • 67
  • 84
  • Are you sure? My superclass is initialized by another controller class. Any calls to the super's properties (which were initialized in `initWithController:`) are valid (they return values, not null). – Clev3r Apr 02 '13 at 17:37
  • Based on the code posted, yes, quite sure. Set a breakpoint where gameValues is initialized and see if it's hit. Unless there's something you didn't include, it won't be. – Catfish_Man Apr 02 '13 at 17:38
  • Imagine that some other class calls initWithController (which it does). Setting a break point @ gameValues does as expected... they are assigned and hold a value. – Clev3r Apr 02 '13 at 17:48
  • Unless you're calling more than one init method on the same object (which is bad! Don't do that!), then your breakpoint hit a call on some other object. Make sure that the address of 'self' when that breakpoint is hit is the same as the address of 'self' in the non-working subclass. – Catfish_Man Apr 02 '13 at 17:49