Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with subclass and superclass using same named properties

Tags:

objective-c

This is something very fascinating I observed today. Maybe that's how Objective-C works but I didn't know about this. See the following code below:

// ATableViewController.h
@interface ATableViewController : UITableViewController
@end

// ATableViewController.m
@interface ATableViewController ()
@property (nonatomic) int volly;
@end

@implementation ATableViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.volly = 5;
}
@end

// BTableViewController.h
@interface BTableViewController : ATableViewController
@end

// BTableViewController.m
@interface BTableViewController ()
@property (nonatomic) int volly;
@end

@implementation BTableViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"%d", self.volly); // returns 5
}
@end

I am not sure why the above is valid. I do understand that I passed a message 'volly' to the object 'self' which in turn probably looked at the value from the super class but shouldn't these be initialized? Some explanation would be of great help. Thanks.

EDIT: This is a big problem IMO though. Considering I don't know any of the private properties defined in the super class, my own set of values might end up being different.

For example, a developer may set a boolean flag hasAppeared in viewDidAppear:. This same value will be set for my subclass instance in viewDidAppear: after the [super viewDidAppear:] call. This will be before I actually get to set it myself.

Currently, the solution is I know exactly the variable used by the super class and I can avoid using the same value but I deem this to be a larger issue than it seems.

EDIT 2: The behavior is consistent with binaries (with only headers) as well as with frameworks where implementation is available.

like image 737
p0lAris Avatar asked Apr 30 '15 22:04

p0lAris


1 Answers

I am answering this without reading all of the comments.

There is no issue here. Both AViewController (AVC) and BViewController (BVC) each have their own private property named volly.

You created an instance of BVC. It can't see the volly property from its parent class (because it is private), just its own.

Now the fun begins.

The viewDidLoad method from BVC is called. It in turn calls [super viewDidLoad]; which of course calls the viewDidLoad from the AVC class. That method, in turn, calls self.volly = 5;.

The confusion seems to be with this line. Remember, self.volly = 5; is really a call to:

[self setVolly:5];

Both AVC and BVC have the (synthesized) setVolly: method. Since self is a pointer to an instance of a BVC object, the call to [self setVolly:5]; results in a call to the setVolly: method in the BVC class despite being called from a method in the AVC class.

Here's the code with some annotations:

The 'BVC' class:

- (void)viewDidLoad
{
    [super viewDidLoad]; // calls the method in `AVC`
    NSLog(@"%d", self.volly); // returns 5
}

The 'AVC' class:

- (void)viewDidLoad
{
    [super viewDidLoad]; // calls the UITableViewController method
    // The following is really [self setVolly:5];
    // Since "self" is a "BVC", the private "volly" property of
    // the "BVC" class is actually set here.
    // The private "volly" property of the "AVC" class will still be
    // 0 after this call.
    self.volly = 5;
}

In the end, the subclass is not using the private property of the parent class. The original premise in the question's title is incorrect.

like image 89
rmaddy Avatar answered Nov 09 '22 15:11

rmaddy