Reputation: 307
The type casting here succeeds
id object = [NSMutableArray array];
NSURLConnection *urlCon = (NSURLConnection*)object;
if ([urlCon isKindOfClass:[NSURLConnection class]])
NSLog(@"urlCon is NSURLConnection");
else if ([urlCon isKindOfClass:[NSMutableArray class]])
NSLog(@"urlCon is NSMutableArray"); // this is called
actually since 'object' is of type NSMutableArray
, the type casting for NSURLConnection
should fail. but it is successful and urlCon
still points to NSMutableArray
, then what is the use of TypeCasting?
Upvotes: 1
Views: 3136
Reputation: 438212
There are two separate issues: One is what type the variable is. The other is what type the underlying object is.
In Objective-C, casting of object pointers doesn't change what the underlying object is. And casting in Objective-C doesn't "succeed" or "fail". It's merely telling the compiler to allow you to treat the variable as if it were actually pointing to an object of the casted type. You generally do this in cases where (a) you have some knowledge of the underlying object that the compiler couldn't reasonably know, and (b) you want to be able to invoke some particular method of some class without the compiler complaining about it. Clearly, that's not the case here, where you've cast the urlCon
variable to expect object
to be a NSURLConnection
, which it isn't.
But isKindOfClass
is a runtime check, which actually looks at what type the underlying object is, and doesn't care what type the variable was cast to.
One common pattern will use isKindOfClass
too determine if an object is a of a particular class, and if so, then will cast it to that particular type so that you can then use methods and/or properties of that class without warnings from the compiler.
So you'll often see this sort of pattern in processing network requests:
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if ([response isKindOfClass:[NSHTTPURLResponse class]]) { // check to see if response is `NSHTTPURLResponse`
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; // if so, cast `NSURLResponse` to `NSHTTPURLResponse`
NSInteger statusCode = httpResponse.statusCode; // now you can use `statusCode` property of `NSHTTPURLResponse`
if (statusCode != 200) {
// Non 200 status code ... so handle HTTP error accordingly here
}
}
// carry on
}];
[task resume];
There are slightly simpler renditions of this pattern, but hopefully it illustrates the idea: You cast when you know (or have programmatically confirmed) something about the type of the object that is pointed to, and you just want to get the compiler on the same page so that you can now use it. You can use isKindOfClass
as a runtime check to confirm that it is, indeed, that type, but the cast lets you use it as such.
Upvotes: 8
Reputation: 16825
What you're experiencing is entirely expected behaviour.
Casting an object of type X, to type Y, does not change the object, it merely forces the object of type X, to look like an object of type Y, even though it's of type X.
What you've done in your example, will most likely invoke lot's of undefined behaviour, if you start calling any function on the object, since NSMutableArray
is not a sub- or superclass of NSURLConnection
.
What you've done is a C style cast. In C, you can cast any two pointer types into each other, there are no checks involved to verify it.
Upvotes: 2