http://stackoverflow.com/questions/8916351/objective-c-alloc-child-class-from-parent-and-use-parent-class-instance-varria
The Problem
The problem started when I was looking at NSURLSession’s dataTaskWithRequest:theRequest method.
1 2 3 4 5 6 7 8 |
NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration: config delegate: nil delegateQueue: [NSOperationQueue mainQueue]]; [[delegateFreeSession dataTaskWithRequest:theRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { ... ... ... }]; |
dataTaskWithRequest returns an instance of NSURLSessionDataTask, which is a child class of NSURLSession.
1 |
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request .... |
Usually, in objective c, a class has an address. It instantiates another object (in the heap), which has a different address.
But how does a parent class return an object of a child class? The child’s parent class is the calling parent? or a different parent?
Basically, it works like this.
Explanation
Create a parent class. Then create a child class. If you were to instantiate the child class, the whole hierarchy sits on one address. Print out the address of self in both the init methods for Parent/Child. You will see that they are the same.
Parent .h/.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
@interface Parent : NSObject { @protected NSString * lastName; //accessible by Child } -(void)createNewChild ; @end //over ride -(instancetype)init { if(self=[super init]) { NSLog(@"%s - address is: %p", __FUNCTION__, self); [self assignLastName:@"hadoooooo ken"]; return self; } return nil; } -(void) assignLastName:(NSString*)newLastName { NSLog(@"%s - assigning protected variable lastName to %@", __FUNCTION__, newLastName); lastName = newLastName; } -(void)createNewChild { //when in a parent class, we instantiate a child class c, is c's parent //the creating parent? or another parent? NSLog(@"%s <--", __FUNCTION__); Child * c = [[Child alloc] init]; [c assignLastName:@"Smith"]; NSLog(@"%s -->", __FUNCTION__); } |
Child .h/.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#import "Parent.h" @interface Child : Parent { } @end #import "Child.h" @interface Child () { } @end @implementation Child //over ride -(instancetype) init { if(self=[super init]) { NSLog(@"%s - address is: %p", __FUNCTION__, self); NSLog(@"Child created successfully....with last name %@", lastName); NSLog(@"%p", super.self); return self; } return nil; } -(void)selfAddress { NSLog(@"%s - %p", __FUNCTION__, self); } @end |
What this means is that if you were to instantiate a child with an address, the parent (grand parent, grand grand parent…etc) class all sits on top of the child class. They are all ONE object, that takes up ONE address.
However, say in your parent class, you instantiate a child class. How would this work?
The parent (with its own address of 0x1001072f0) instantiates the child class (with its own address 0x100400080) in the heap.
That itself should tell you that we are dealing with 2 separate objects here. If the child accesses its parent properties, it would be doing so in its OWN parent. (The parent that sit on top of the child) The parent that shares the same address with the child.
IF you want the child to access the calling parent, simply pass in the calling parent as a parameter.
So what’s up in NSURLSession’s dataTaskWithRequest
Hence, this is what’s happening when I see NSURLSession call a method, and returns a child class object.
1 2 3 4 5 6 7 |
NSURLSession * session = .... NSURLDataSession * t = [[session dataTaskWithRequest:theRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { ... ... ... }]; |
inside dataTaskWithRequest, its creating a child class NSURLDataSession on the heap, which its own NSURLSession parent. They both sit on another address. This other object will process the request, then return execution to the completion block.